OmniAICreator/Qiita-1.07M huggingface dataset:
ksnctf 19 ZIP de kure 150pt

#問題

https://ksnctf.sweetduet.info/problem/19

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/da6f930f-5323-ad0d-3baf-ef62ca91376d.png)

#解いてみた

アスキーアートは意味ありません。
とのこと。

とりあえずzipをダウンロードして開いてみます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/d7a9f48a-055a-ea53-648b-b3d656d88daf.png)


なるほど。
パスワードをクラックして解凍すると中にflagがあるっていう問題のようです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/4532e97c-76c7-e2ee-d760-bb1416d937b8.png)


パスワード付きzipでもデフォルトだとファイル名は見れる仕様なんです。
ということで見てみると案の定見ることができました。
右側にヒントが出てるんですが、逆にこの文字ってどうやって設定してるのか不明。

google翻訳すると

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/f614349b-8417-a243-f869-792a3fb433b0.png)


「平文攻撃に弱いことが知られている」と書かれていますが、たぶん文脈的に既知平文攻撃ってことですかね。

既知平文攻撃というのは相当簡単にいうとzip内の圧縮されたファイルに1つでも既知のファイルがあった場合、パスワードが推測できるという攻撃です。詳しく知りたい人は検索してみてください。

そして「圧縮じゃないよ」的なことも書かれていたので、エクスプローラで開いてみると確かに圧縮率のところが0%になってる。
初めて見た。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/86eb1f95-d4d5-eacc-660b-3a22bd3dd640.png)


中に入っているファイルを整理すると以下2つです。

```
flag.html
Standard-lock-key.jpg
```

当然、flag.htmlに答えが書いているでしょうから、このファイルは未知です。
ということはもう一つのStandard-lock-key.jpgが既知ということ？
知らないファイルなので検索してみる。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/93233b9b-0652-4637-7f4f-81ca9d9a7d94.png)

なんとwikipediaで出てきたんですが、というか画像ファイルが出てきただけですが。
たぶんこれなんでしょう。
ひとまずダウンロードします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/56b03fd4-018b-1bfc-56f6-d12bdc4ddfd5.png)

サイズがいくつかあったので2つダウンロードしたんですが、どちらも250KBから大きく外れていた。
これは罠なのか？
もう一度wikipediaのページに戻ってファイルの履歴とかいう項目を見てみたら衝撃の事実が判明しました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/091ddba4-b06d-ad88-9fd3-9386643148a3.png)

何者かが2018/8/6に更新してる。
ということで古い方が250KBなのでこれをダウンロードします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/455e5c20-cc62-d60b-2a2d-580d8588b206.png)

ぴったり250KBです。
PkCrackというソフトを使って攻撃します。
が、Windowsは32bit版しかありません。
64bitでもたぶん動くだろうと思ってやってみたところ「サポートされていない16ビットアプリケーション」というエラーが出て実行できませんでした。
32bitじゃなくて16bitのソフト？？？
相当昔に作られたものなんでしょうか。

仮想マシンのUbuntu使います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/019d6c66-48a8-6062-ad47-ff1f98d798ea.png)

時間がかかるのかと思ってたら1分もかからず完了しました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/6521dc4a-445a-3650-f7b6-ce32b54d5a4e.png)

作成されたzipファイルを解凍するとパスワードなしで解凍することができました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/a8b94168-20fe-eb00-557f-511a5ef74e70.png)

flag.htmlを開くとflagが書いてました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/7270fc26-e41a-34fa-c818-9f6799bbc6af.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/eaa1a063-d4d9-7822-4dd3-1473bd4d4258.png)
barryvdh/laravel-elfinder導入時にvendor:publishが機能しなかった件

barryvdh/laravel-elfinderを導入しようとしたときに遭遇した事象についてメモ。
https://github.com/barryvdh/laravel-elfinder

# vendor:publishを実行してもファイルがコピーされない
barryvdh/laravel-elfinderのconfigファイルを自身のプロジェクトへコピーするためvendor:publishを実行した。
readmeにコマンドの記載があったのでコピペして実行

【記載されていたコマンド】
php artisan vendor:publish --provider='Barryvdh\Elfinder\ElfinderServiceProvider' --tag=config

【実行結果】
Publishing complete.

実行自体は問題なく行えた。
しかし、肝心のconfigファイルがコピーされていない。。。

いろいろ試した結果、
--provider='Barryvdh\Elfinder\ElfinderServiceProvider'のシングルクォートを削除、
またはダブルクォートに変更するとコピーできた。

【正常動作しないコマンド】
php artisan vendor:publish --provider='Barryvdh\Elfinder\ElfinderServiceProvider' --tag=config

【正常動作するコマンド】
（シングルクォート削除）
php artisan vendor:publish --provider=Barryvdh\Elfinder\ElfinderServiceProvider --tag=config
（ダブルクォート使用）
php artisan vendor:publish --provider="Barryvdh\Elfinder\ElfinderServiceProvider" --tag=config

#まとめ
正直頑張って解決するほどのことでもなかった気がするがlaravelの勉強になったので良し！
（手動でファイルをコピーすれば済む話なので。。）

シングルクォートではダメな理由はわからなかったので、
詳しい人、分かる人がいればコメント下さいm(_ _)m
IBM Watson Assistantにアクセスできない！権限設定のハマりどころ5つ


![image.png](https://qiita-image-store.s3.amazonaws.com/0/96286/3e196d00-7cca-48d9-3280-26cd0f222aaa.png)

# TL;DR
普段IBM Cloudを使い慣れていない私がWatsonAssistantを使ってハマったポイントは...
* 一つのメニューにたどり着くための方法が多い
* 権限の名前とできることの繋がりがちょっと分かりにくい
* コンソールのUIに難があり、設定変更が保存されたかどうか分かりづらい

# Watson Assistantに新規ユーザーを追加する手順
## 1. ユーザーを招待する
ハマり1. `IAM`やユーザー一覧などの設定あh、左上のハンバーガーメニューにありません。
ハマり2. Userの一覧を表示するためのメニューが2つあります。
* Manage >  Account > Users
* Manage >  Security > Identity and access 

以下のように、 `Manage`メニューからユーザー追加&権限の設定を行います。
<img width="1279" alt="スクリーンショット 2019-01-12 12.25.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/96286/05d5228c-9552-b842-a147-d7b26acb1823.png">

## 2. ユーザーに Cloud Foundry Organizations の権限を追加する。
ハマり3. Cloud Foundry Orgの表示方法も２通りあります。
* Users > Cloud Foundry access > View Organization Details
* Manage > Account > Cloud Foundary Orgs

`Users > Cloud Foundry access > View Organization Details` で表示する場合
![image.png](https://qiita-image-store.s3.amazonaws.com/0/96286/ae6ba217-e354-8d75-ab2d-60d75891b4f9.png)

`Manage > Account > Cloud Foundary Orgs` で表示する場合
![image.png](https://qiita-image-store.s3.amazonaws.com/0/96286/1837a05e-89fe-6dfd-6ebb-ef41072c5046.png)

ハマり4. Managerの権限ではWatson Assistantは参照できません。 Developer権限が必要
※ Managerは他の人にCloud Foundary Orgの権限を渡す権限のようです。

ハマり5. Save と表示されているが、この `Save`は実はボタン！ 押さないと保存されない!
<img width="1278" alt="スクリーンショット 2019-01-12 12.35.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/96286/d08404a9-d18d-e394-c1fa-4f017830de08.png">

# まとめ
普段AWSを使い慣れていることもあって、他のクラウドは戸惑うことも多いです。
まとめてみて、IBM Cloudのこれはこれで便利かも、と思いました（例えばメニューにはコンピューターリーソース以外の設定は入れない）
他の困った人の参考になれば幸いです。
そもそもHTMLって何？？

#  この記事を書こうと思った理由

Webアプリケーションには必須のHTMLを深く勉強せずにここまできてしまったので、一度立ち止まって勉強しようと思った。自分用のメモでもある。

# HTMLとは
HTMLとはHyper Text Markup Language（ハイパーテキスト・マークアップ・ランゲージ）の略。

ハイパーテキスト・・・ハイパーリンクを埋め込むことができるテキスト
ハイパーリンク・・・クリックそのリンク先に移動できるみんながよく使うリンクのこと
（上の二つをまとめてハイパーリンクテキストという）

マークアップ・・・目印をつけるという意味。文章の中身にある見出し、段落、表などのそれぞれの役割をコンピュータが理解できるように書くこと（タグのこと）

まとめるとHTMLは、「リンクを用いた他のページの情報やタグを用いたそれぞれの要素がわかりやすく書かれている文書」と言える

適当に書くとコンピュータが理解できないので、HTMLのルールのもとで書きましょうって感じ。

#XHTMLとの違い

HTMLと似た言語でXHTMLという言語がある。

XHTMLは、XMLから生まれた言語で、XMLの特徴を引き継いでいる。

HTMLとの大きな違いは、XHTMLでは独自のタグを作ることができる。そのためHTMLに比べて自由度の高いページが作れるが、ルールが厳密なので使いこなすのはHTMLよりは難易度が高い。

また宣言の違いもあるので注意が必要。

# <!DOCTYPE html> って何？？

HTMLを書いていると一番最初に書くこれ。そもそも何なのか。

一言で言うと、「DTOを宣言するもの」らしい。

DTOとは文書型の定義のこと。つまりこの文書は何で書いているかを示すもので、HTML５は　<!DOCTYPE html>　の１行で宣言できる。(htmlタグより前に書く必要がある)

HTMLのバージョンやXHTMLなどの違いによって宣言するものが違うので、使うときに調べると良い。

# 気になったいくつかのタグ

個人的に気になったタグをいくつか調べてみた。

###headタグ

文書のヘッダ情報を書く場所。

ヘッダ情報とは、そのHTMLに関するメタデータのことで、メタデータとは、title,style,metaなどのタグのこと。

要はそのHTMLの基本的な情報をheadタグの中に書く必要がある。


###metaタグ

metaタグはheadタグより細かいメタ情報を書くタグ。

主に、文字エンコーディングの指定、作者の設定、ツールやソフトウェアの設定など色々な設定ができる。

SEO対策をする人はmetaタグで対策をすることも多いらしい。

###navタグ

ナビゲーションを表すタグ。

ナビゲーションとは主にウェブページ内のリンクを貼る場所。headerタグを一緒に用いることが多い。

全ての箇所に囲む必要がなく、主要な箇所だけ囲むだけで綺麗に反映される。

footerはfooterタグだけで十分なこともある。

###scriptタグ
文書中にJavaScriptやVBScriptなどのスクリプトを埋め込むためにタグ。

書くときにtype属性は必須で、言語名を指定する。

使うときはscriptに対応していないブラウザのために全体を、<!--～//-->で囲んで使用する。（〜が中身）


###emタグ

囲んだ箇所をイタリック体にする。（最初は何も変化してないと思ってました、、）

#まとめ

良い復習にはなったかな！
以上です！
Dockerコンテナの設定をやり直す

コンテナで色々作業した後(その環境のみに依存するサーバーの設定やDBの中身等を想定)
にポート設定の追加やマウントフォルダの再設定したくなった場合で
再度作業をする時間がなかったりする場合に使う。
**その環境特有の設定やDB等もイメージに入ってしまうので運用に応じて気を付ける必要がある。**
（環境構築用のイメージとしては相応しくない、アプリケーションのバックアップイメージとするなら問題ない）

```:images
REPOSITORY          TAG                  IMAGE ID    
<name>              latest         aaaaaaaaaaaa
```

# 使用中コンテナをリネーム

```
docker rename {CONTAINER_NAME} {CONTAINER_NAME}-20190101
```

# 使用中のイメージのバックアップを作る

```
docker tag <name>:latest <name>:20190101
```

```:images
REPOSITORY          TAG                  IMAGE ID    
<name>              latest         aaaaaaaaaaaa
<name>              20190101       aaaaaaaaaaaa
```

# 使用中コンテナからイメージを作る

コンテナを停止させてから作成する

```
docker stop {CONTAINER_NAME}-20190101
docker commit {CONTAINER_NAME}-20190101 <name>:latest
```

```:images
REPOSITORY          TAG                  IMAGE ID    
<name>              latest         bbbbbbbbbbbb
<name>              20190101       aaaaaaaaaaaa
```

latestが上書きされる

元のコンテナの作成時のdocker runコマンドと同じように実行する
（ここでポートやマウントの設定を変更したければ修正する）
Skim/Emacs で SyncTeX

MaC で SyncTeX をするメモです．
Mac で PDF ビューワに Skim，エディタは Emacs を使用しました．

TeX についてある程度の基礎知識を仮定します．

## SyncTeX とは

> SyncTeX は TeX ソースを開いたエディタと PDF ビューワとの間での相互ジャンプを実現する仕組みです

TeX Wiki が参考になります: [SyncTeX](https://texwiki.texjp.org/?SyncTeX)

SyncTeX には，2つのモードがあります:

1. PDF から TeX ファイルにジャンプ (backward search, inverse search)
2. TeX ファイルから PDF にジャンプ (forward search)

SKim の wiki が参考になります: [TeX-PDF Synchronization](https://sourceforge.net/p/skim-app/wiki/TeX_and_PDF_Synchronization/#tex-pdf-synchronization)

TeX ファイルが長く，ファイル分割しているような場合に便利です．


## backward search の方法

Skim で開いた PDF の任意の場所で Command-Shift-Click を押すと，エディタで TeX ファイルの対応する位置にジャンプできます．

まず，TeX のコンパイル時に，オプションで `-synctex=1` を指定する必要があります．(詳細略)
これにより，`*.synctex.gz` が生成されますが，これは TeX ファイルと PDF の位置の対応を記録するもの (のはず) です．

また，emacsclient を有効にしておく必要があります．(詳細略)

あと，Skim の環境設定で，エディタを指定する必要があります．
Skim → Preferences → Sync で， Preset の中に Emacs もあり，これを選べばよいはずです．

私の場合はこれではうまく行かず，エディタを Custom にして，emacsclient のフルパスを指定することで解決しました．[^1]


[^1]: パスが通す方法もありそうですが，フルパスを指定してできたので，これで良いことにしました．


## 雑感

SyncTeX について調べると，設定がややこしそうな印象を受けますが，backward search だけであれば設定は単純です．
検索の際に，forward/backward search が何か分かっていると調べやすくなると思います．

forward search についてはエディタ側で設定が必要のようです．
また必要になったときに調べる予定です．
play 2.6でaccess Logを出力

# 目的
開発中、PlayをAPIサーバーで使っていると、フロントエンド側からのリクエストがどう来ているのか確かめたくなることがあります。

ひとまずどのURLにリクエストが来たのかロギングします。

# 手順
「play 2.6 request log」で調べると[公式ページ](https://www.playframework.com/documentation/2.6.x/ScalaHttpFilters)が出てくるので、こちらをそのまま使えました。

filtersパッケージ内に以下ファイルを作成します。


```scala:LoggingFilter.scala
package filters

import javax.inject.Inject
import akka.stream.Materializer
import play.api.Logger
import play.api.mvc._
import scala.concurrent.{ExecutionContext, Future}

class LoggingFilter @Inject() (implicit val mat: Materializer, ec: ExecutionContext) extends Filter {

  def apply(nextFilter: RequestHeader => Future[Result])
           (requestHeader: RequestHeader): Future[Result] = {

    val startTime = System.currentTimeMillis

    nextFilter(requestHeader).map { result =>

      val endTime = System.currentTimeMillis
      val requestTime = endTime - startTime

      Logger.info(s"${requestHeader.method} ${requestHeader.uri} took ${requestTime}ms and returned ${result.header.status}")

      result.withHeaders("Request-Time" -> requestTime.toString)
    }
  }
}
```

application.confに作成したLoggingFilterを使うよう設定

```
play.filters {
  enabled += filters.LoggingFilter
}
```

`sbt run`で再起動すると以下ログがでるようになりました！


 [info] application - GET / took 1ms and returned 200


ちなみに、POSTリクエストのボディも見たいと思ったのですが、以下解答を見ますとFilterの設定ではできないようです。
Filterのapplyメソッドの引数がRequestHeaderなので、ボディ情報がとれないのもその証拠ですね。


https://stackoverflow.com/a/25492776
(※雑な意訳)
こちらによると、playframeworkはreaactive systemに則っているので、リクエストのヘッダ情報だけでフィルタは動作できるとのこと。
フィルタでリクエストのボディーまでパースして処理しようとすると遅くなるとも。
Mac OS mojave で MacPorts Emacs を使う

# 2019/1/12現在 emacs-app は表示に課題あり

MacPorts 使って，普通に emacs-app をインストールしても，mojaveではレンダリングされずに表示ができない

emacs-app does not render 
https://trac.macports.org/ticket/57217
というチケットが出てますな．

本件は，もともとは Emacs 本体の課題です
http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=7946445962372c4255180af45cb7c857f1b0b5fa

emacs-app にはまだパッチが取り込まれていないので
解決策は emacs-app ではなく，emacs-app-devel をつかえと

```
sudo port uninstall emacs-app
sudo port install emacs-app-devel
```

# でも inline 入力どうするん？

そのまま emacs-app-devel 入れたら日本語入力でハマったので
patch あててコンパイル必要
https://gist.github.com/takaxp/77bfc397a2c807281453e8b8b2dfb2b7

```
sudo port uninstall emacs-app
sudo port -f patch emacs-app-devel
cd /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_tarballs_ports_editors_emacs/emacs-app-devel/work/emacs-20190111/
sudo patch -p1 < ~/emacs-26-mojave-inline.patch
sudo port -f install emacs-app-devel
--->  Computing dependencies for emacs-app-devel
--->  Configuring emacs-app-devel
--->  Building emacs-app-devel
--->  Staging emacs-app-devel into destroot
--->  Installing emacs-app-devel @20190111_0
--->  Activating emacs-app-devel @20190111_0
--->  Cleaning emacs-app-devel
--->  Scanning binaries for linking errors
--->  No broken files found.
--->  No broken ports found.
```

とかで，とりあえずOK
Bash 5.0の新機能：カーソルの画面行移動

Bash 5.0のNEWSファイルをさくっと翻訳したエントリー[「bash 5.0のNEWSファイル私訳」](https://qiita.com/emasaka/items/47eaa5fb5a01572fcc17)を先日書きました。

この中のReadline 8.0の新機能として、カーソルの画面行移動機能がありました。

```
b. キーに割り当てられるコマンドに新しく`next-screen-line' and
   `previous-screen-line'があります。カーソルを画面行のそれぞれ次と前
   の行の同じカラムに移動します。
```

さっそく試してみましょう。

Bash 5.0のコマンドラインから、Ctrl-↓に`next-screen-line`を割り当てます。

```console:
$ bind '"\e[1;5B": next-screen-line'
```

同様にCtrl-↑に`previous-screen-line`を割り当てます。

```console:
$ bind '"\e[1;5A": previous-screen-line'
```

コマンドラインで、1行が1画面行を超えるように文字を入力します。

```console:
$ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
```

ここでCtrl-↓とCtrl-↑を押すとカーソルが画面行を移動することがわかります。
CircleCIでWordpressとかのモニタリングしようぜ？

Wordpressでリンクが壊れていて機会損失した経験はありますか？
海外からアクセスしたWordpressのパフォーマンスが悪すぎて機会損失した経験はありますか？
この記事では、Wordpressや任意のサイトを自動でテストして、それらの機会損失を予防する方法をご紹介します。

## 自動テストの発想

Jekyll、Hugoなどの静的ファイルジェネレータやNuxt.jsはサイトas codeになっているので、CircleCIで自動テストしやすいですよね。
WordpressはDBで管理されているので、同じようにはいきませんが、本番環境のWordpressをCircleCIでチェックすれば良いです。
Wordpressのなんらかの更新からCircleCIをトリガーできれば、デプロイ前のチェックができないこと以外は、実質同じような状態にできます。

## リンクチェックプラグインは漏れる

内部でリンクチェックしてくれるツールはありますが、
プラグインをいろいろ使っていると、
チェックはパスしても、外部から見て破綻していることがあります。

## テスト実行用のDocker image

イメージ名: contribu/webtester
dockerhub: https://hub.docker.com/r/contribu/webtester
リポジトリ: https://github.com/contribu/webtester

## CircleCIから使う方法

CircleCI用のリポジトリを作り、
以下のようなconfig.ymlを配置。

```yaml
version: 2
jobs:
  build:
    docker:
      - image: contribu/webtester
        environment:
          - LANG: ja_JP.UTF-8
          - LANGUAGE: ja_JP.UTF-8
          - LC_ALL: C.UTF-8
    working_directory: ~/repo
    steps:
      - checkout
      - run:
          name: run tests
          command: |
            cd /app
            mkdir -p /tmp/test_results
            bundle exec ruby main.rb test \
              --seed_urls=https://example.com/ \
              --allowed_url_patterns="https://example\.com" \
              --interval=1 \
              --timeout=60 \
              > /tmp/test_results/result.html
      - store_test_results:
          path: /tmp/test_results
      - store_artifacts:
          path: /tmp/test_results
          destination: test_results
```

## 結果の見方

/tmp/test_results/result.html に出力しています。
CircleCIならアーティファクトから見れます。

- Size: バイト数
- Total Time: リクエストを開始してからダウンロードが完了するまでの時間
- From Link Count: 被リンクページ数 (allowed_url_patternsに含まれるもののみカウント)

## 動作

seed_urlsで与えられたURLを起点に、allowed_url_patternsで与えた正規表現パターンに一致するURLをクロールし、最後にレポートを出力します。

### intervalについて

allowed_url_patternsで与えた正規表現パターンに一致しないURLはリクエストを飛ばしません。

allowed_url_patternsが自分で管理するサーバーのみの場合は、intervalは小さめで大丈夫だと思います。

allowed_url_patternsに自分で管理するサーバー以外のサーバーが含まれる場合は、intervalが違法にならないように注意してください。

## CircleCIのサーバーの場所

少なくとも日本以外っぽいです
https://discuss.circleci.com/t/where-are-the-build-servers-located-geographically/20571

## テスト

--tests=/path/to/test1.rb /path/to/test2.rb

このようにしてテストを追加できます。デフォルトで、not foundとinterval server errorをチェックするテストがついています。

テストは以下のように書きます。インターフェースはtestのみです。
以下の変数を組み合わせてテストし、エラーにする場合は{ error: "error message" }を返します。

result[:url]
result[:status]
result[:total_time]
result[:size]
result[:from_urls]
result[:to_urls]

```ruby
register_test(
  test: lambda do |result|
    if result[:status] >= 400 && result[:status] < 500
      {
        error: 'Not Found'
      }
    end
  end
)
```

## ライセンス

この記事に掲載されたコードのライセンスはCC0
NDI経由で受信した映像をOBSで配信する（Mac編）

Mac上のOBSでNDIを利用するための手順が意外と見つからなかったので書き留めておきます。

# できること
iPhoneのカメラ映像をNDI経由で受信してMac上のOBSから配信できるようにします。

# 前提条件
OBS Studioのインストールは既にされているものとします。
macOS: 10.14.2 (Mojave)
OBS Studio: 22.0.3
obs-ndi: 4.5.3

# iPhone に JustWifiCam をインストール
カメラ映像をNDI送信できる「[JustWifiCam](http://www.justbroadcaster.com/justwificam/)」というアプリを iPhone にインストールし
ます。
NDI送信ができるアプリはNewtek社純正をはじめ有料アプリはあるのですが無料のものはほとんどありません。JustWifiCamも課金しないとロゴが消えませんがちょっとしたテストには使えます。

アプリを起動して画面中央にある丸いボタンを押せば何も設定しなくてもNDI送信が開始されます。

![IMG_0867.PNG](https://qiita-image-store.s3.amazonaws.com/0/149785/3616c229-3f9e-2836-ef4c-609ab02e135b.png)

# obs-ndi のインストール
OBS Studio の NDIプラグインである obs-ndi をインストールします。
GitHubにMac用の pkg が用意されています。
[Network A/V in OBS Studio](https://github.com/Palakis/obs-ndi)
インストール手順に書かれていますが pkg だけでなく NDI runtime もインストールする必要があるので注意しましょう。

# OBS Studio の設定
obs-ndiのインストールが終わるとソースの追加メニューに「NDI™Source」が選択できるようになっています。

<img width="363" alt="スクリーンショット 2019-01-12 9.56.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/149785/e3a6a1c3-1ba1-5e1e-c6ac-f1c8638aa154.png">

ソースに追加してプロパティを確認すると「Source name」に「端末名(JustWifiCam)」と表示されます。同一ネットワーク上に複数のNDI送信デバイスがあっても必要なソースを指定する事ができます。

<img width="362" alt="スクリーンショット 2019-01-12 10.13.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/149785/6c39e829-9952-7733-04c1-104b9805946d.png">

デバイスを見つけて画面が表示されるまでに少し時間がかかる場合があります。

見えない場合はWiFi接続を確認しましょう。基本的に同じWiFiにiPhoneとMacを接続すれば自動的にデバイスを見つけてくれますが、WiFi APの設定によっては同一ネットワーク上の機器の通信を禁止している場合があります。特にパブリックスペースではそのような設定の場合も多いので注意が必要です。

これでiPhone上のカメラ映像をソースにOBSで配信する事ができるようになりました。

<img width="360" alt="obs-ndi.png" src="https://qiita-image-store.s3.amazonaws.com/0/149785/4d201dae-42c1-9e4f-fa74-17a0a02a6edf.png">


# 活用方法
単にiPhoneカメラの映像を配信するだけであれば他にも方法があると思いますが、NDIを使うことによって様々な活用ができます。
PCのキャプチャ画面を転送、[ラズパイを使って映像転送]
(https://qiita.com/kitazaki/items/eeb710a78c657024f844)、[TouchDesignerを配信](https://qiita.com/n_bando/items/3176cf4664fe76f0b333)などQiita上にも色々と記事がありますが、自分でも活用方法を探って記事にしたいと思います！

# 参考サイト
[OBS向けNDIプラグインを試してみた。](https://medium.com/ngeair/obs%E5%90%91%E3%81%91ndi%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3%E3%82%92%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F-9f7aa1f7c853)
Metamaskのrpcエラーが出たとき

- コントラクトは合っている
- testでも正常に動作する


だけど，Metamaskを使用してtxを送信しようとするとエラーが出る．

# 結論：Metamaskを再インストール

[TX doesn't have the correct nonce - Metamask](https://ethereum.stackexchange.com/questions/30921/tx-doesnt-have-the-correct-nonce-metamask)に色々な解決策が書いてある.
自分はMetamaskを一旦削除して，再インストールすると何事もなかったように正常に動作するようになった．PCをシャットダウンした後などに，たまにこの現象になる．


# 参考資料
[TX doesn't have the correct nonce - Metamask](https://ethereum.stackexchange.com/questions/30921/tx-doesnt-have-the-correct-nonce-metamask)
Unity拡張エディタメモ

### スクロールで横スクロールバーを非表示かつ幅を整える
```
var Width = 200;
scrollPos = EditorGUILayout.BeginScrollView(scrollPos, GUIStyle.none, GUI.skin.verticalScrollbar);
EditorGUILayout.LabelField("", new[] { GUILayout.Width(Width), GUILayout.Height(0) });
```
BeginScrollViewでGUILayout.Widthを指定してしまうと、縦スクロールバー表示位置が悪い
#WindowsタスクスケジューラでPythonを走らせる

#WindowsタスクスケジューラでPythonを走らせる
　Windowsタスクスケジューラを用いて以前作成した[Amazonの価格監視システム](https://qiita.com/kawa-Kotaro/items/f417e7a5776a8ece0d0b)を定期的に実行します．[こちら](https://qiita.com/__init__/items/95ac1d45858b8b24a59c)の記事を参考にしました．この記事はWindows8のものでしたが，Windows10でもまったく同じでした．

##基本タスクの作成

まず，Windowsタスクスケジューラを起動します.

![スクリーンショット (2).png](https://qiita-image-store.s3.amazonaws.com/0/327279/8986c175-2bd2-eeb1-fcc4-a3d6a5b0d3f1.png)

起動したら基本タスクの作成を選択します．ここではタスクの名前を設定します


![キャプチャ(3).PNG](https://qiita-image-store.s3.amazonaws.com/0/327279/b51883c9-5507-6f56-a94d-0b1eb63bfbe3.png)


##トリガーの設定
次にトリガの設定です．いつ実行するか，どれぐらいの頻度で実行するかを設定します．

![キャプチャ(4).PNG](https://qiita-image-store.s3.amazonaws.com/0/327279/7f26e948-80b6-1a6f-560e-f606d41b56e5.png)

初めのオプションを設定すると,詳細設定に移ります．

![キャプチャ(5).PNG](https://qiita-image-store.s3.amazonaws.com/0/327279/cb601bb9-2013-cfaa-2c11-8508b55a70c4.png)

今回は毎朝7時に実行するように設定しました．

##操作の設定
次に操作の設定です．

![キャプチャ(6).PNG](https://qiita-image-store.s3.amazonaws.com/0/327279/efc51bb7-627c-bed2-b4a9-34217155a9c8.png)

Pythonを実行するためにはプログラムの開始を選択します．

![キャプチャ(7).PNG](https://qiita-image-store.s3.amazonaws.com/0/327279/b9dbdb11-272a-5ca4-421e-35d720888a0d.png)

スクリプトにはpython.exeのパスを，引数のオプションには実行するファイル名，オプションには実行するファイルまでのパスを指定します．

##完了
最後に完了画面が表示されます．

![キャプチャ(8).PNG](https://qiita-image-store.s3.amazonaws.com/0/327279/c2c92689-6fee-f0c7-23d9-ebf7998ab691.png)



##タスクの削除
作成したタスクはタスクスケジューラのライブラリに保存されます．ここから削除や設定変更を行うことができます．

![キャプチャ(9).PNG](https://qiita-image-store.s3.amazonaws.com/0/327279/3f0ef989-1165-f4f9-204a-85d424cce209.png)


##おわりに
これで定期的にAmazonの価格をチェックできるようになりました．これ以外のプログラムも定期的に実行できるようにしてクリエイティブな毎日を過ごしましょう!!
Pythonで、非同期処理（コルーチン）と、同期処理（マルチプロセス）を併用する

以下、cpuをたくさん使う処理を別プロセスとしてフォークし、pipeで通信。親は、asyncioでコルーチンで回る、ような例です。

```py
import asyncio
import aiohttp.web
from multiprocessing import Process, Queue, Pipe
import time

async def websocket_handler(request):
    print('Websocket connection starting')
    ws = aiohttp.web.WebSocketResponse()
    await ws.prepare(request)
    print('Websocket connection ready')
　　#親プロセスで子プロセスから受信
    print(parent.recv())
    parent.send('hello2')
　　#非同期処理
    async for msg in ws:
        print(msg)
        if msg.type == aiohttp.WSMsgType.TEXT:
            print(msg.data)
            if msg.data == 'close':
                await ws.close()
            else:
                await ws.send_str('pong')
    print('Websocket connection closed')
    return ws

def f2(child):
    #重い同期的処理、例えば画像処理
    print('f2 start')
    child.send('hello')
    time.sleep(3)
    print(child.recv())

if __name__ == '__main__':
　　#通信チャネルとしてパイプを準備しておいて、別プロセスをフォーク
    parent, child = Pipe()
    p = Process(target=f2, args=(child,))
    p.start()
　　#非同期処理のメインループ起動
    loop = asyncio.get_event_loop()
    app = aiohttp.web.Application(loop=loop)
    app.router.add_route('GET', '/ws', websocket_handler)
    aiohttp.web.run_app(app, host='192.168.0.6', port=8080)
    p.join()
```
Goでサーバリソース情報を取得する

# やること

Goでリソースを取得してみる。今回は以下のライブラリを利用しました。


- `cloudfoundry/gosigar`
  - https://github.com/cloudfoundry/gosigar

- 実行環境
    - MacOS(10.14.1)
    - go1.11.2 darwin/amd64

- このライブラリを利用してリソース情報を取得する書き方をまとめてくれています。
  - https://github.com/cloudfoundry/gosigar/tree/master/examples

- 取得するリソース
  - Uptime
  - ロードアベレージ
  - メモリ使用量

# ソースコード


```main.go
package main

import (
	"fmt"
	"github.com/cloudfoundry/gosigar"
)

// MB
func format(val uint64) uint64 {
	return val / 1024 / 1024
}

func main(){
	uptime := sigar.Uptime{}
	uptime.Get()

	// UPTIME
	fmt.Printf("Uptime: %s \n", uptime.Format())

	avg := sigar.LoadAverage{}
	avg.Get()


	// Load Average
	fmt.Printf("Load Average %.2f, %.2f \n", avg.One, avg.Five)

	mem := sigar.Mem{}
	mem.Get()

	// Memory Used[MB]
	fmt.Printf("Memory[MB] total=%d, used=%d, free=%d \n", format(mem.Total), format(mem.Used), format(mem.Free))

}
```

- 実行結果

```
Uptime: 15 days, 14:05
Load Average 2.09, 2.49
Memory[MB] total=8192, used=8112, free=79
```

# まとめ
`cloudfoundry/gosigar` のライブラリを利用して、システムリソース情報を取得してみました。
次は、このライブラリを利用せずにシステムリソースを取得するコードを書いていきたいと思います。
for文における無限リストの生成発生 ~python学習1.03~

#for文で無限ループに陥る
Pythonのfor文はC言語のものとは違うらしい。

```qiita1.py
>>> words = ['Haruka', 'Lovely', 'Morishima']

>>> for w in words:
...     if len(w) > 7:
...         words.insert(0, w)

>>> print(words)
```
これは無限ループが発生し、


```qiita2.py
>>> words = ['Haruka', 'Lovely', 'Morishima']

>>> for w in words[:]:
...     if len(w) > 7:
...         words.insert(0, w)

>>> print(words)
['Morishima', 'Haruka', 'Lovely', 'Morishima']
```

では、無限ループが発生しません。

##なぜ無限ループが発生しないか
qiita1.pyでは、words配列そのものを渡していますが、
qiita2.pyでは、words配列の参照をコピーして渡しています。


参照を渡した場合ではinsert()されても、words[:]から得た配列を扱っているため無限ループは発生しません。
words[1:]だと、['Lovely', 'Morishima'] のみです。
つまり、words[:]では、同じ値を持つ別の配列がコピーされて渡されているということではないでしょうか。

無限ループが発生する、配列そのものを渡した場合には、'Morishima'でinsert()が行われ、
配列の要素が1つずつ後ろに下がります。これにより、for文で再度おなじ'Morishima'が
評価されることで無限ループが発生します。


Javaでシングルスレッド環境でも、for文からListの要素を変更すると、
 *java.util.ConcurrentModificationException*例外が投げられるのは
やさしい世界だったのかもしれない。

#開発環境
Windows10 64bit
Python 3.7.1
PyCharm 2018.3.2


#参考資料
学習に用いているものとして、以下の２つがメインです。
・[詳細! Python 3 入門ノート](https://www.amazon.co.jp/%E8%A9%B3%E7%B4%B0-Python-%E5%85%A5%E9%96%80%E3%83%8E%E3%83%BC%E3%83%88-%E5%A4%A7%E9%87%8D-%E7%BE%8E%E5%B9%B8/dp/4800711673/ref=sr_1_1?ie=UTF8&qid=1546995770&sr=8-1&keywords=%E8%A9%B3%E7%B4%B0%21Python3%E5%85%A5%E9%96%80%E3%83%8E%E3%83%BC%E3%83%88)
・[Python公式ドキュメント](https://docs.python.jp/3/tutorial/index.html)
はてなダイアリーの下書きをWSSE認証でダウンロード

はてなダイアリーの下書きをエクスポートする方法がわからなかったので、纏めてダウンロードするツールを書いてダウンロードした。

WSSEとかクッソ懐しいな。。今はJWTとかJSON APIが全盛だけど、gRPCとかが流行ってJSONテクノロジが今のXMLテクノロジと同じように懐しいもの扱いされる時代が来るんだろうか。。

# 仕様

- http://developer.hatena.ne.jp/ja/documents/auth/apis/wsse
- http://developer.hatena.ne.jp/ja/documents/diary/apis/atom

# コード

ユーザ名、apitokenとページ数は手動で設定する必要がある。apiトークンは、"投稿用メールアドレス"の名前部分になる。

https://github.com/okuoku/hatenadraftread

```javascript
const MAXPAGE = 12;
const hatena_username = "mjt";
// Acquire key at https://www.hatena.ne.jp/{{USERNAME}}/config/mail/upload
const hatena_apitoken = "XXXXXXXXXX";
// See AtomPub API at http://developer.hatena.ne.jp/ja/documents/diary/apis/atom
// See WSSE API at http://developer.hatena.ne.jp/ja/documents/auth/apis/wsse

const wsse = require("wsse");
const rp = require("request-promise-native");
const fs = require("fs");

var token = wsse({username: hatena_username, password: hatena_apitoken});

var page = 1;

async function readpage(page){
    let options = {
        url: "http://d.hatena.ne.jp/" + hatena_username + "/atom/draft?page=" + page.toString(),
        method: "GET",
        headers: {
            "X-WSSE": token.getWSSEHeader()
        }
    };
    console.log(options.url);
    const res = await rp(options);
    return res;
}

function doread(page){
    readpage(page).then(content => {
        fs.writeFileSync("page" + page.toString() + ".xml", content, "utf-8");
        if(page != MAXPAGE){
            doread(page+1);
        }
    });
}

doread(1);
```

# 感想

誰か(正規の方法を)説明してくれよ！ (ﾛﾝﾘｰｳｪｰｲ)
【#PowerApps】ComboBoxが選択されていないときにページ遷移をさせない方法

# 記事の移動
https://www.powerplatform.work/blog/2019/06/16/PowerApps-ComboBox%E3%81%8C%E9%81%B8%E6%8A%9E%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%81%A8%E3%81%8D%E3%81%AB%E3%83%9A%E3%83%BC%E3%82%B8%E9%81%B7%E7%A7%BB%E3%82%92%E3%81%95%E3%81%9B%E3%81%AA%E3%81%84%E6%96%B9%E6%B3%95/
こちらに移動しました。
こちらに書かれている内容は最新情報でない可能性があります。

# 概要
コンボボックス(ComboBox)でアイテムが選択されていないときにエラー通知やページ遷移をさせない方法です。

# 施策

IsBlank関数とCountRows関数の両方を使用する。
どちらか片方だけでも、一見うまくいきそうですがケースに抜けが生じます。

# コード

ComboBoxの複数選択は許可しています。

``` ComboBox1.OnCange
If(
    IsBlank(ComboBox1.SelectedItems) || CountRows(ComboBox1.SelectedItems) = 0,
    Concurrent(
        UpdateContext({IsValidate: true}),
        Notify(
            "選択されていません",
            NotificationType.Error
        )
    ),
    UpdateContext({IsValidate: false})
)

```

Notify()は任意です。

あとはIsValidate をボタン等の遷移するためのコントロールに設定してやります。

```Button1.OnSelected
If(
    IsValidate,
    Notify(
        "エラーが出ている個所を訂正してください。",
        NotificationType.Error
    ),
    Navigate(
        Screen2,
        ScreenTransition.Fade
    )
)

```


# なぜIsBlank()が必要？

コンボボックスControlはユーザーがコンボボックスを選択する前はDefaultselectedItems プロパティを使用して選択した項目を初期化しています。

ただし、コンボボックスコントロールのSelectedプロパティとSelectedItemsプロパティは**ユーザーの操作によって選択された**アイテム一覧を表示するために使用されます。したがって、手動でコンボボックスコントロールから値を選択しないと、Selected式は空を返します。

その為、IsBlank関数が必要となってきます。

# なぜCountRows()が必要？

ユーザーがコンボボックスを選択後にアイテムを削除した場合、すでにユーザーが１度手動で値を選択したため、Selected式は空を返さなくなるので必要です。
Qiita / Github のMarkdownは実はHTML対応しているので、TwilogからTwitterの全ツイートを貼り付けることさえ可能。やらないけど。

MarkdownがそもそもHTML対応してるんだっけ？未確認。



https://twilog.org/YumaInaura/date-190111

# Twilog

自分のツイートをすべて記録してくれるサービス。

![image](https://user-images.githubusercontent.com/13635059/51055165-658dc600-1622-11e9-851e-68ed1d542f9b.png)

# HTML を取得できることに気づいた‥！

画面右下のボタン。

![image](https://user-images.githubusercontent.com/13635059/51054916-a76a3c80-1621-11e9-89f3-18b610ab9654.png)

# こんな隠れ神機能が‥！


![image](https://user-images.githubusercontent.com/13635059/51054926-acc78700-1621-11e9-968d-834313396981.png)

# はてなブログのHTML編集モードにHTMLをコピー

![image](https://user-images.githubusercontent.com/13635059/51055237-a5ed4400-1622-11e9-86ef-11b9a2da1b0e.png)

# 投稿結果

![image](https://user-images.githubusercontent.com/13635059/51055033-f912c700-1621-11e9-8182-1ccb47e848e2.png)

[@yumainaura 2019/01/11 Twitter 全てのツイートまとめ by @twilog - いなうらゆうま yUmaiNaURA](http://yumainaura.hateblo.jp/entry/2019/01/12/043328)

# HTML対応しているブログやサービスなら何でも転載できそう

# Qiitaの場合

単にツイート転載はしないけど。機能の確認。

![image](https://user-images.githubusercontent.com/13635059/51054949-c23cb100-1621-11e9-9521-da1dafe9cf25.png)

# Githubの場合

![image](https://user-images.githubusercontent.com/13635059/51054963-cbc61900-1621-11e9-8289-54f73cdf423e.png)

# 表示件数・取得件数の限界はあるかもしれない


![image](https://user-images.githubusercontent.com/13635059/51055670-e39e9c80-1623-11e9-9fa0-42018b6399d5.png)


---

https://twitter.com/yumainaura

https://github.com/YumaInaura/YumaInaura/issues

https://github.com/YumaInaura/YumaInaura/issues/330








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Windows Cabocha python3.7.2 でのエラーとの闘い

#もう自前ビルドしたくないpip使いたい…
めちゃくちゃ苦労したのでメモ。ぐだぐだ長いので飛ばしたいかたは結論をどうぞ。
まずは、「[WindowsにCabocha 0.68をいれてPythonで係り受けを解析してみる](https://qiita.com/mima_ita/items/161cd869648edb30627b)」を参考に進めます。

##バージョン
python 3.7.2
cabocha 0.69
mecab 0.996

#外部シンボルhogehogeが未解決です*
[WindowsでCaboCha-Python3バインディング](https://qiita.com/ayuchiy/items/d8afcffb27fcc10f6947)
上記に従って、pythonとmecabを32bitにそろえる。

あとあとわかるのですが、PythonのバージョンにあったBuild Tools / Visual Studioを入れる必要はないです。あとでエラーで指定されるので、ここではとりあえずbit数だけ揃えてください。

#unable to find vcvarsall.bat
英語、しかもcythonの話ですが、[error: Unable to find vcvarsall.bat](https://stackoverflow.com/questions/2817869/error-unable-to-find-vcvarsall-bat) のとある一文
cython uses distutils, you need to import setuptools which monkey-patches distutils: 

`import setuptools`
この一文をsetup.pyの頭にでも入れることで解決します。

#each element of 'ext_modules' option must be an Extension instance or 2-tuple
また英語ですが、[error: each element of 'ext_modules' option must be an Extension instance or 2-tuple](https://stackoverflow.com/questions/21594925/error-each-element-of-ext-modules-option-must-be-an-extension-instance-or-2-t) より、

`from setuptools import setup, Extension, Command`
に変更します。

#Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": https://visualstudio.microsoft.com/downloads/

先ほどPythonのバージョンにあったBuild Tools / Visual Studioを入れる必要はない、といったのはこのエラーのためです。Python3.7に合わせるなら14.1のはずなんですよね…。統一してほしい。
2017が14.1で、2015が14.0のようです。14.1ではエラーが解消されませんでした。
で、リンク先の下部の以前のバージョン→再頒布可能パッケージおよびビルド ツールから、2015のBuildToolsをダウンロード＆インストールします。

#結論
エラーがでるまで「[WindowsにCabocha 0.68をいれてPythonで係り受けを解析してみる](https://qiita.com/mima_ita/items/161cd869648edb30627b)」通り進める
python mecab を32bitにそろえる
setup.py に `from setuptools import setup, Extension, Command` の一文を加える
Microsoft Build Tools 2015 をインストールする
LaravelでSessionをコンストラクタで使うときの注意点

### LaravelでSessionに何かを入れておく処理を書いて、一度アクセス(セッションに保存)しておき、、

```php
class LoginUserController extends Controller
{
    public function index(Request $request)
    {
            $token = 'hoge';
            // セッションIDの発行
            session()->regenerate();
            // セッションへデータを保存する
            session(['token' => $token]);
           
            $token = session('accessToken'); // セッションからデータを取り出す
            Log::debug($token); // ちゃんと表示される
        }
}
```

### 別のControllerのコンストラクタで(以後のアクセスの際に)Sessionから値を取り出そうとすると、あるはずの値がない。

```php
class HogeController extends Controller
{
    public function __construct()
    {
        $token = session('accessToken');
        Log::debug($token);
    }

    public function index()
    {
        // 
    }
}

```

### logは空文字。

---

## 対処法

### Kernel.phpの以下を変更すると治る。

```php:app/Http/Kernel.php

class Kernel extends HttpKernel
{
    protected $middleware = [
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \App\Http\Middleware\TrustProxies::class,
        \Illuminate\Session\Middleware\StartSession::class,                   // ここを追加
    ];

    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            // \Illuminate\Session\Middleware\StartSession::class,  　　　　　 // コメントアウト
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];
}

```
PythonでASCIIパーセントエンコーディングする

```python
from urllib.parse import quote

quote('いろはにほへと')
#=> '%E3%81%84%E3%82%8D%E3%81%AF%E3%81%AB%E3%81%BB%E3%81%B8%E3%81%A8'
```

参考
ドキュメント urllib.parse — Parse URLs into components https://docs.python.org/3/library/urllib.parse.html#urllib.parse.quote
How to percent-encode URL parameters in Python? https://stackoverflow.com/a/1695199/8776028
CSRF対策とは何？

Webアプリケーションを作成するにあたって、「CSRF対策」という言葉を聞いたことはありませんか？
そこで、今回は「CSRF対策」について記載します。


#CSRF対策とは？
「CSRF」とは、リクエストを強要させることを指します。
つまり、別のサイトにコンテンツ上したはずのリンクが実は罠で、これを踏ませてWebアプリケーションの重要な処理（例えば、ネットショッピングの最終決済など）を呼び出すように誘導することを表すのです。
よって、このような悪徳攻撃に対策をとるのが、「CSRF対策」です。

この攻撃の対象となるのは、フォームがサーバーから供給されたものだと確認していないWebアプリケーションです。
そのため、罠であるリンクを埋め込まれないようにする対策が必要なのです。


##CSRFの対策方法とは？
では、その対策とは一体何でしょうか？

使うキーワードは、**openssl_random_pseudo_bytes**と**bin2hex**です。

###openssl_random_pseudo_bytes
これは、疑似乱数のバイト文字列（いわゆる普通の文字列）を生成する働きがあります。
[詳しくはコチラ](http://php.net/manual/ja/function.openssl-random-pseudo-bytes.php)


###bin2hex
これは、バイナリ（2進数）のデータを16進表現に変換する働きがあります。
[詳しくはコチラ](http://php.net/manual/ja/function.bin2hex.php)
Ubuntu 18.10のSlack Clientにて日本語入力ができない

## 事象
Ubuntu 18.10をThinkpad X260にインストールし、ワクワク構築していたところ、**Slack Clientにて日本語入力ができない**事象が発生

## 環境
```bash
takuma@X260:~$ cat /etc/*-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.10
DISTRIB_CODENAME=cosmic
DISTRIB_DESCRIPTION="Ubuntu 18.10"
NAME="Ubuntu"
VERSION="18.10 (Cosmic Cuttlefish)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.10"
VERSION_ID="18.10"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=cosmic
UBUNTU_CODENAME=cosmic
```

## まずは
ぐぐったらこんな記事が出てきた。確かに、Store版 (Snap)を使ってたのでアンインストールして、debパッケージからインストールしました。

[Ubuntu18.04LTSでSlack日本語入力が出来ないときの対処方法 - Qiita](https://qiita.com/akjgskwi/items/a65d396e353e31f235d2)

debパッケージダウンロード先 → [Linux | ダウンロード | Slack](https://slack.com/intl/ja-jp/downloads/linux)

```bash
# Store版SlackをRemove
takuma@X260:~$ sudo snap remove slack-desktop

# 依存関係を解決したいので、gdebiをインストール
takuma@X260:~$ sudo apt install gdebi

# ダウンロードしたdebパッケージをインストール
takuma@X260:~$ sudo gdebi slack-desktop-3.3.4-amd64.deb
```

## これで使えると思いきや…
GNOME Launcher？でSlackを検索してもアプリが表示されない（インストールされていないように見える）。`dpkg`ではインストールできている感じ。

```bash
takuma@X260:~$ dpkg -l | grep slack
ii  slack-desktop                              3.3.4                                         amd64        Slack Desktop
```

## 解決
とりあえずインストールできているなら、直接バイナリ起動すればええんちゃうかと、`which`でpath調べて直接起動

```bash
takuma@X260:~$ which slack
/usr/bin/slack
takuma@X260:~$ /usr/bin/slack
(electron) 'app.makeSingleInstance(cb)' is deprecated. Use 'app.requestSingleInstanceLock() and app.on('second-instance', cb)' instead.
Creating Slack Application
```
※用が住んだらCtrl+CでKillしてしまいましょう。

## このあとめちゃくちゃ起動した。
一度起動したら検索にも引っかかるし、サイドバーのお気に入りに登録すればそのままSuper+Nで起動もできた。
ちなみに、Store版で入れていた設定はちゃんと保持されていた。めでたしめでたし。

以上
AdobeXDのPlugin開発を始める

AdobeXDが無料で触れるようになったみたいです。
Plugin開発も簡単に始められましたので、デザイナーさんの大変な作業を減らしていきましょう。:muscle:

## 環境構築

- [公式サイト](https://www.adobe.com/jp/products/xd.html)からAdobeXDをダウンロード

## HelloWorldしてみる

- AdobeXDを開く

- ヘッダーメニューの「プラグイン > 開発版 > 開発フォルダーを表示」を選択

- Finderから「helloworld」ディレクトリを作成

- 下記2ファイルを作成

```js:main.js
function sayHello(selection, documentRoot) {
        console.log("Hello World!");
}

module.exports.commands = {
    helloCommand: sayHello
};
```

```json:manifest.json
{
    "id": "YOUR_ID_HERE",
    "name": "Name of Your Plugin",
    "version": "0.0.1",
    "description": "Description of your plugin.",
    "icons": [],
    "host": {
        "app": "XD",
        "minVersion": "13.0.0"
    },
    "uiEntryPoints": [
        {
            "type": "menu",
            "label": "Hello World",
            "commandId": "helloCommand",
            "shortcut": { "mac": "Cmd+Shift+P", "win": "Ctrl+Shift+P" }
        }
    ]
}
```

- ヘッダーメニューの「プラグイン > 開発版 > プラグインを再読み込み」を選択

- ヘッダーメニューの「プラグイン > 開発版 > Developer Console」を選択

- ヘッダーメニューの「プラグイン > Hello World」を選択

- Developer Consoleに「Hello World!」と表示される
M5Stack MPD client

#概要

先日投稿した[赤外線リモンデコーダ](https://qiita.com/tt-yawata/items/92adb5ddb19ff1d07178)を使ったMPDクライアントです。
M5Stackのボタンと赤外線リモコンでMPDの操作ができます。
RaspberryPiのGPIOにいろいろ接続せずに操作パネルが付けられないかと考え、試作してみました。

##機能
- MPDのボタン操作
- MPDの赤外線リモコン操作
- 演奏中の曲名表示

##ソースコード

ソースコードはこちらに置きました。
[https://github.com/tt-yawata/m5mpdclient.git](https://github.com/tt-yawata/m5mpdclient.git)

###設定方法

WiFi APとMPDサーバの設定はコードに埋め込んでありますのでそちらを修正してください。
m5mpdclient.ino : 24行目

```arduino
const char ssid[] = "Your SSID";
const char pass[] = "Your PASS";
```
MPDサーバは、IPアドレスまたはサーバ名で指定できます。
m5mpdclient.ino : 28行目

```arduino
//mpd server
// by IP address
//const char mpdserver[] = "IP:192.168.xxx.xxx";
//by server name
const char mpdserver[] = "moode";
//char mpdserver[] = "volumio";
//const char mpdserver[] = "smpd";
```
###ボタン操作

M5StackのAボタンでモードを選択してB/Cボタンで操作します。
Aボタンを押すたびに0⇒1⇒2⇒3⇒4⇒0⇒…とモードが変化します。
ボタンを離して5秒するとモード0に戻ります。

|モード|Bボタン|Aボタン|
|:---:|:---:|:---:|
|0|play/pause|stop|
|1|previous|next|
|2|seek 0|seek end|
|3|Shuffle|repeat|
|4|volume -5|volume +5|

※赤外線受信器を接続しなくてもとりあえずボタンだけでも操作できます。

###赤外線リモコン

赤外線受信器はGPIO21に接続しています。GPIOピンは変更可能です。
詳細はこちらもご参照ください。
[https://qiita.com/tt-yawata/items/92adb5ddb19ff1d07178](https://qiita.com/tt-yawata/items/92adb5ddb19ff1d07178)

m5mpdclient.ino : 55行目

```arduino
const gpio_num_t irPin = GPIO_NUM_21;
```

テストに使用しているリモコンはこちらです。
[https://www.akiba-led.jp/product/1489](https://www.akiba-led.jp/product/1489)
サンプルコードでは以下のようにマッピングしています。

![ir_remote.png](https://qiita-image-store.s3.amazonaws.com/0/331423/fcf42c49-5181-422f-1a3d-088d4ec54c08.png)
m5mpdclient.ino : 61行目

```arduino
// IR remote command for
// https://www.akiba-led.jp/product/1489
const String ir_play = "N00ffc23d"; // pause
const String ir_stop = "N00ff6897";
const String ir_next = "N00ff02fd";
const String ir_prev = "N00ff22dd";
const String ir_home = "N00ffa25d";
const String ir_end = "N00ffe21d";
const String ir_repeat = "N00ff906f";
const String ir_random = "N00ff629d";
const String ir_volup = "N00ffa857";
const String ir_voldown = "N00ffe01f";
```
リモコンコードはシリアルポートに出力されます。
他のリモコンを使用する際にそのリモコンのボタンを押してコードを確認できます。
シリアル出力が不要な場合はコメントアウトしてください。
m5mpdclient.ino : 734行目

```arduino
    Serial.println(ircode);
```

###MPDサーバについて

RaspberryPiにて[Volumio](https://volumio.org),  [moOde audio player](http://moodeaudio.org/),[symphonic-mpd](http://mpd.sytes.net/ja)で動作確認しています。

- volumio: playlistの管理がオリジナルのため、previous, stopコマンドが動作しません。
- symphonic-mpd: デフォルトでは6600ポートが閉じられていますので設定変更が必要です。
- moOde audio player: 特に設定はありません。

##注記

- WiFi AP, mpdサーバの設定がコード埋め込みになっているなど使い勝手が良くないと思います。サンプルコードと思っていますので、ご自由に改造してください。（不具合もありそうですので、改良版を公開していただけるとうれしいです）
- Volumoは[websocket API](https://volumio.github.io/docs/API/API_Overview.html)ですので、専用のクライアントを作ったほうが良いと思っていますが手がついていません。
- 画面は、表示内容やデザインなど改良が必要と思います。

ちょっと宣伝モード。弊社にて開発・製造している[Terra-BerryDAC/HPA](https://www.terratechnos.com/products/terraberrydac/)と組み合わせたイメージです。
[![s-s-IMG_20181226_113632.jpg](https://qiita-image-store.s3.amazonaws.com/0/331423/4f71b824-fa6a-7ce0-b82b-8266d708f6f3.jpeg)](https://www.terratechnos.com/products/terraberrydac/)

##参考にさせていただいたサイト

- [M5Stackで日本語表示](https://qiita.com/taront/items/7900c88b9e9782c33b08)
- その他
TrueDyanmicBranchその２


小改良したので備忘録

#Falseブロック

条件分岐のelseブロックを処理できるようにしてみた。
処理結果

```
	float4  Local0 = ProcessMaterialColorTextureLookup(Texture2DSampleBias(Material_Texture2D_0,Material_Texture2D_0Sampler,Parameters.TexCoords[0].xy,View_MaterialTextureMipBias));
	float  Local1 = (Local0.r - 0.50000000);
	float3  Local7 = 0.0;
	[branch]
	if(Local1 > 0.0){
	float4  Local2 = ProcessMaterialColorTextureLookup(Texture2DSampleBias(Material_Texture2D_1,Material_Texture2D_1Sampler,Parameters.TexCoords[0].xy,View_MaterialTextureMipBias));
	float4  Local3 = ProcessMaterialColorTextureLookup(Texture2DSampleBias(Material_Texture2D_2,Material_Texture2D_2Sampler,Parameters.TexCoords[0].xy,View_MaterialTextureMipBias));
	float3  Local4 = (Local2.rgb + Local3.rgb);
	float3  Local8 = 0.0;
	Local7 = Local4;
	}
	else{
	float4  Local5 = ProcessMaterialColorTextureLookup(Texture2DSampleBias(Material_Texture2D_3,Material_Texture2D_3Sampler,Parameters.TexCoords[0].xy,View_MaterialTextureMipBias));
	float3  Local6 = (Local5.rgb * Local0.rgb);
	Local7 = Local6;
	};
	float3  Local9 = (Local7 + Material_VectorExpressions[1].rgb);
	float4  Local10 = ProcessMaterialColorTextureLookup(Texture2DSampleBias(Material_Texture2D_4,Material_Texture2D_4Sampler,Parameters.TexCoords[0].xy,View_MaterialTextureMipBias));
	float  Local11 = (Local10.r - 0.20000000);
```

#divergent gradient error回避

仕組みの問題なので最適化を回避する

	FRegexPattern TextureSampleUsingGradientPattern(TEXT("Texture.*SampleBias"));
で検索してさらに右辺値にローカル変数があるものを最適化から除外した


![image.png](https://qiita-image-store.s3.amazonaws.com/0/223804/666f19f6-c0af-1cb9-7c3e-54a2abfd07ea.png)

#計測

LandScapeのマテリアルからMIP0固定のテクスチャフェッチがなくなったのでちょっと引き気味のカメラで
DyanmicBranchのありなしで計測

画像のランドスケープだと茶色い部分がベースのレイヤーで動的分岐によって処理が端折られている部分です。

##ブランチなし

![image.png](https://qiita-image-store.s3.amazonaws.com/0/223804/a5091f11-0ec4-af31-de73-0051fa2fef62.png)

##ブランチあり

![image.png](https://qiita-image-store.s3.amazonaws.com/0/223804/f1c5d28f-9c20-d5d5-7b50-44fe3f988d58.png)


BasePassが4.5msから3.5msになった。
[Ruby on Rails] dependent: :destroyの罠

当たり前なことなのかもしれないが、はまったので記載

##Rails環境
```sh
$ rails -v
Rails 5.2.2
```

##想定場面
Itemを複数所持するUserがいる

```ruby
class User < ActiveRecord::Base
  has_many :items, dependent: :destroy
end
```
```ruby
class Item < ActiveRecord::Base
  belongs_to :user
end
```

##発生した問題

下記のような二つの処理が同時に走った時

```ruby
# スレッド１
user = User.first
user.with_lock do
	[時間のかかる処理]
	user.items.create!
end

# スレッド２
User.first.destroy!
```

一見Userにレコードロックがかかっているので問題なさそうだが、[時間のかかる処理] 中にスレッド２が走るとスレッド１で作成されるItemが残ってしまう。

##原因
dependent: :destroyの削除順は 子(Item) → 親(User) なので ロックのかかっていないItemの削除処理が走ってしまう。（Userの削除は `with_lock do{}` プロックを抜けた後に実行される）

##解決策
User削除するときもロックをかけてやる。

```ruby
# スレッド２
User.first.with_lock do
  User.first.destroy!
end
```

解決策はいろいろありそう。
Arduinoでクルマのエンジンが動く？　オープンソースECU Speeduino (5)燃料噴射・点火信号の確認

前回記事
[(4)回転数の確認](https://qiita.com/covao/items/374a4c86cc352a59f206)
#燃料噴射信号と点火信号を確認
Speeduinoから出力されるインジェクターの燃料噴射信号とイグニッションプラグ点火信号を計測します。

##用意するもの
- [前回使用したArduino Mega+Arduinoの環境](https://qiita.com/covao/items/374a4c86cc352a59f206)
- ロジックアナライザ 　アマゾンでUSB接続タイプのものが1000円～入手できます:sweat_smile:
　（ここでは、8ch USBロジックアナライザとオープンソースソフトの[sigrok](https://sigrok.org/)を使用しています）

##計測するI/Oポート

| Arduino Mega I/O |ロジックアナライザ Ch|
|:-----------------|------------------|
|pin 8:インジェクタ1|D0|
|pin 9:インジェクタ2|D1|
|pin 40:イグニッションコイル1|D2|
|pin 38:イグニッションコイル2|D3|
|pin 19:クランク角センサ|D4|
|pin 18:カムセンサ(2ndクランク角センサ)|D5|

ロジックアナライザで、上記の信号を計測します。
![IMG_1064.JPG](https://qiita-image-store.s3.amazonaws.com/0/329764/80c0b7c2-eaef-01c5-6ad3-89b59d0c24f5.jpeg)

#TunerStudioとDeviceDruidの起動
[前回](https://qiita.com/covao/items/374a4c86cc352a59f206)と同様に、TunerStudioとDeviceDruidを起動し、回転数を1500[rpm]のクランク角信号を入力します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/329764/3d29b2d9-9fbe-9b99-e54a-f3c73e749f34.png)

ロジックアナライザで出力波形を確認してみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/329764/ff60f5b1-bd2a-d6ca-43b0-50131dcd3616.png)
*D0:INJ1, D1:INJ2, D2:IGN1, D3:IGN2, D4:Crank, D5:Cam

**INJ1,INJ2のパルスが出力されていません。**:worried:

Tuning>VE Table Multiply VE value by MAP:Baro ratioをNoに設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/329764/565751d6-a510-abd7-6e6b-66bdee30460a.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/329764/252e8d32-b5ae-81a3-292d-cb9665d2f7bf.png)
*D0:INJ1, D1:INJ2, D2:IGN1, D3:IGN2, D4:Crank, D5:Cam

インジェクタのパルスが出力されるようになりました。:smiley:
**まだ、IGN1,IGN2がOff状態で点火していません。**:worried:
*TunerStudio下のインジケータ、Ign Cut(Boost)がOnになっているようです。*
吸気圧センサの入力がないため、Engine MAP([Manifold Air Pressure Sensor](https://speeduino.com/shop/index.php?id_product=12&controller=product))が最大値となってしまっていることが原因のようです。

次に、Accessories>Boost ControlのBoost CutをOffにしてみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/329764/6a5be240-d9d3-36df-0eb2-c8eadc1c1a80.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/329764/50a8eeec-dbd9-e8f8-109f-4a73ac9450c5.png)
*D0:INJ1, D1:INJ2, D2:IGN1, D3:IGN2, D4:Crank, D5:Cam

無事、IGN1,IGN2の信号が出力されました。:grinning:

##参考書籍
- [電子制御エンジンの基礎・応用―電子制御ガソリン噴射の基礎からコンピュータの制作まで (ビギナー・ノート・シリーズ)](https://www.amazon.co.jp/dp/4789830667/)

20年以上前に出版された本ですが、現在、10倍くらいの値段となっています。本に書かれている自作ECUは、後にE&Eシステム社FREEDOMコンピュータ（マニア向けECU）として商品化されたようです。現在では、販売とサポートを終了していますが、このメイカーズスピリッツは、時代を超えて、Speeduinoへ受け継がれていくのかもしれません．．．

##最後に

[次回](https://qiita.com/covao/items/60f7adf1cc0fcdf31880)は、Speeduinoの制御により、燃料噴射パルス幅と点火タイミングが変化するところを確認する予定です。
Dockerについて改めて整理してみた(2019年版)

# Docker 2019年 

4年くらい前にガッツリ構築を担当したDocker。最近はAWSやAzure案件が中心でコンテナから離れていたのですが、久しぶりにいろいろややこしくなっているDockerについて整理してみました。

※Windows周辺のサービス名称は適当です。全体の流れがわかればと言うことで概要です。
※2019年12月末に少し更新しました。


## Docker の流れ
Dockerのリリースから最近までの大きな流れ　

[1] Linux で Docker がリリースされる 2013
[2] Docker FreeBSD版 がリリースされる 2016
[3] Docker for Windows がリリースされる 2016
[4] Docker for Mac がリリースされる 2016
[5] Windows Server 2016 が Docker を正式サポート 2016
[6] Ubuntu on WSL (Windows Subsystem for Linux) で Dockerが動作 2018
[7] Solaris が Docker をサポート予定
[8] Docker on WSL2

## Docker の分類

##### [1] Docker
Linuxネイティブの元祖Docker
Linux kernelを利用したオリジナルのDocker 
Linuxコンテナ機能を提供

##### [2] Docker (FreeBSD)
FreeBSD上で動作するDocker
FreeBSDのLinuxバイナリ互換機能を利用して、Linuxコンテナ機能を提供
FreeBSDで実行されたLinuxプロセスがコンテナとして隔離され実行される
Linuxバイナリ互換機能有効化とファイルシステムとしてZFSの利用が必須
提供されているDockerのバージョンは古め。

##### [3] Docker for Windows
Windows上で動作するDocker 
Linuxエミュレーション
Linuxの仮想マシンが動作し、Linux kernelと共にLinuxコンテナ機能を提供
Windowsの文字コードやOSの仕様に引っ張られ、\\(バックスラッシュ)、半角スペース前後などの文字に関連した固有のエラーが昔はよく出た(今も？)ので注意が必要。

##### [4] Docker for MacOSX
MacOSX上で動作するDocker
Linuxエミュレーション
Linuxの仮想マシンが動作し、Linux kernelと共にLinuxコンテナ機能を提供

##### [5] Docker Container Service (Windows Server 2016)
Windowsネイティブ
Windows向けに作られたDocker。LinuxコンテナをWindows上で動作させるのではなく、WindowsのプロセスをDockerコンテナとして提供するサービス。動作するのはWindowsコンテナ。つまり、IISのコンテナなどを作成し、稼働させることができる。

##### [6] Docker on Ubuntu on Windows (Windows Subsystem for Linux) 
Linuxネイティブ
WindowsOS上でLinuxコンテナ機能を提供。Windows Subsystem for LinuxがプロセスをLinuxのシステムコールをリアルタイムでNTカーネルのシステムコールへ変換し、NT Kernelに渡す。これにより、NTカーネル上でLinuxのDockerが動作し、Linuxプロセスがネイティブ動作する。

##### [7] Docker (Solaris)
次期Solarisでサポート予定と発表されてから4年くらい経っているようですが、動きはあまり見えません。Solaris Zone（Solarisコンテナ）をDockerと統合するようです。詳細は不明。(2019年12月更新）

Docker coming to Oracle Solaris
https://blogs.oracle.com/solaris/docker-coming-to-oracle-solaris

##### [8] Docker on WSL2
Windows上でエミュレートではなくネイティブLinux環境を提供するWSLの次世代バージョンであるWSL2がMicrosoftから発表されました。Windows10上の特殊な小さなVM上で完全なLinux Kernelを搭載するためサポートできないシステムコールがなくなり、今まで以上に互換性が向上するようです。

Docker社はWSL2に最適化した次のバージョンのDocker Desktopをリリースし、Kuberntesをサポートするようです。今までのバージョンではHyper-V上で構築したLinux上で動作していました。


## 関連する技術
chroot 
FreeBSD - Jail
Solaris Zone (旧Solarisコンテナ)
Redhat Linux - OpenVZ

以上、非常にややこしいDockerについてまとめてみました。