OmniAICreator/Qiita-1.07M huggingface dataset:
HerokuでPHPをデプロイする

# HerokuでPHPをデプロイする
※本記事は2018年08月22日時点の情報を元にした内容ですが、2020年4月時点では上手くいくみたいです。
また、今回はGithub連携としない場合について書いています。

## はじめに
PHPを2ヶ月間学習していたので、PaaSであるHeroku上で動かして公開してみようと思いました。

## セットアップ
### Herokuのユーザー登録
[公式サイト](https://jp.heroku.com/)から画面に従ってメールアドレス等を入力します。
プランはとりあえず無料にしました。

### heroku toolbeltのインストール
CLIからHerokuを操作するためのツールです。
公式サイトの[The Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli)から自分のOSにあう方法でインストールします。私はUbuntuを使っているのでターミナルからインストールしました。

### Herokuにログイン
ターミナル(コマンドプロンプト)を開いて`heroku login`と入力し、登録したメールアドレスとパスワードを入力します。`logged in as {メールアドレス}`と表示されればログイン完了です。

## アプリの作成からデプロイ

### Herokuでアプリの作成
ターミナルから作成もできますが今回はブラウザを使います。
ダッシュボードに移動したあと`Create New App`を押し、アプリ名を入力して`Create app`を押します。

### ローカルリポジトリの作成
作成後は`Deploy using Heroku Git`に従いターミナルに入力していきます。**GitHubと連携もできますが**今回はシンプルにHerokuだけで行います。

```bash
$ cd my-project/
$ git init
$ heroku git:remote -a {作成したアプリ名}
```
`my-project`はアプリ名等に変えたほうが分かりやすいです。

### コミット
gitにpushする準備ができたのでコミットしてきます。
`git init`したディレクトリにphpファイルを追加します。

```index.php
<?php
  echo 'Hello World!';
?>
```
`index.php`の保存後、コミットします。

```bash
$ git add .
$ git commit -m 'initial commit'
```
`-m`はエディタを開かずにコミットコメントを入力するオプションです。
自分の場合`*** Please tell me who you are.`とエラーが出たので内容に従って設定しました。

```bash
$ git config --global user.email "you@example.com"
$ git config --global user.name "Your Name"
```
### プッシュ
プッシュするとHeroku側でデプロイしてくれます。

```bash
$ git push heroku master
```
`WARNING: No 'composer.json' found!`と警告がでますが、プッシュとデプロイができました。
アプリのページを開きます。

```bash
heroku open
```
ブラウザで`Hello World!`と表示されていれば成功です。

## PHPのバージョンの指定

PHPのバージョンはいくつか指定できるようです。今回は指定していないので自動的にPHP5になっています。実際にコードを書いていくときは先にバージョンを決めておきましょう。先程のWORNINGがでた`composer.json`を編集します。
[Heroku PHP Support \| Heroku Dev Center](https://devcenter.heroku.com/articles/php-support#supported-versions)

```composer.json
{
  "require": {
    "php": "^5.6.0"
  }
}
```
これで5.6.0以降のバージョンを指定できます。(`^`を使わない限定的な指定は推奨されていないようです。)
次に、`composer.json`の内容を反映するために

```bash
$ composer update
```
を実行したあと、
`git add .`、`git commit`、`git push`とすればアプリに反映されます。

`composer update`で

```
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - This package requires php ^5.6.0 but your PHP version (7.2.9) does not satisfy that requirement.
```
とエラーが出た場合、phpのバージョンが違うので変更します。
参考：[ubuntu 16\.04 で複数のバージョンの PHP を使う、切り替える \- Enjoi Blog](http://blog.enjoitech.com/article/259)

## おわりに
Herokuを使えば簡単にPHPを使ったWebサイトを公開できました。無料プランなので制限はついていますが、ポートフォリオ等のテスト用途としては十分でしょう。
SAPシステムをZabbixで監視する。(Linux版)

# はじめに
前回投稿から半年がたってしまいました。。。反省。

Zabbix を利用してSAPシステムの稼働監視を行う際に簡単なシェルスクリプトを作成し、 監視できるようにした話です。

本稿でのSAPは「SAP Netweaver ABAP/JAVA」を示すこととします。

# 概要
Zabbix は　`UserParameter`を利用して任意のOSコマンド、シェルスクリプト標準出力を監視できます。そこで、SAPの稼働状況を示す値を標準出力に出力するシェルスクリプトを作成し監視します。

## 「SAPの稼働状況」とは

本稿の中でSAPの稼働状況は`sapcontrol`コマンドの`GetProcessList`関数で出力される`dispstatus`のことと定義します。
以下の表は`dispstatus`に出力される値とその値が示す稼働状態、スクリプトの出力値です。

| dispstatus | 状態 | スクリプトの出力値|
|:------:|:-----------:|:-----------:|
|GREEN   |稼働中        |3| 
|YELLOW  |起動中        |2|
|RED     |障害          |1|
|GRAY    |停止中        |0|


# 実装
## 前提

- Zabbix Agentはrootユーザで動作させること
- sapstartsrv プロセスは別途プロセス監視すること (sapstartsrvが停止していると`sapcontrol`コマンドで稼働状況を取得できなくなるため)

 
## シェルスクリプトの流れ

以下の流れで処理します。

1. `saphostctrl`コマンドの`ListInstances`関数でサーバにインストールされているSAPインスタンスのインスタンス番号を取得する。
2. 取得したインスタンス番号ごとに`sapcontrol`コマンドの`GetProcessList`関数でSAPインスタンスの稼働状況を取得する。
3. `GREEN` > `YELLOW` > `RED` > `GRAY` の順でもっとも下位の状態をホスト全体のSAP稼働状況として標準出力に出力する。

## 監視シェルスクリプトソースコード
```bash:check_sap_status.sh
#!/bin/bash
readonly SAPHOSTCTRL="/usr/sap/hostctrl/exe/saphostctrl"
readonly SAPCONTROL="/usr/sap/hostctrl/exe/sapcontrol"

readonly CNS_INITIAL=4
readonly CNS_GREEN=3
readonly CNS_YELLOW=2
readonly CNS_RED=1
readonly CNS_GRAY=0
### Functions ####
function check_status() {
  local sys_status="${CNS_INITIAL}"
    for nr in `"${SAPHOSTCTRL}" -function ListInstances | awk '{print $6}'`
    do
      sys_status="$(check_instance_status "${sys_status}" "${nr}")"
    done
    echo "${sys_status}"
}
function check_instance_status() {
  local status="${1}"
  local nr="${2}"
  while read dispstatus
  do
    case "${dispstatus}" in
      GREEN)  test "${status}" -ge "${CNS_GREEN}" && status="${CNS_GREEN}"
              ;;
      YELLOW) test "${status}" -ge "${CNS_YELLOW}" && status="${CNS_YELLOW}"
              ;;
      RED)    test "${status}" -ge "${CNS_RED}" && status="${CNS_RED}"
              ;;
      GRAY)   test "${status}" -ge "${CNS_GRAY}" && status="${CNS_GRAY}"
              ;;
    esac
  done < <("${SAPCONTROL}" -format script -nr "${nr}" -function GetProcessList | grep dispstatus|awk '{print $3}')
  echo "${status}"
}

### Main Proc ####
check_status
```

## UserParameter 設定
```config:/etc/zabbix/zabbix_agentd.d/userparameter_sap.conf
UserParameter=sap.status[*],/etc/zabbix/plugin/sap/check_sap_status.sh
```

## アイテム設定(Zabbix Server)
![2018-08-22 22_33_55.png](https://qiita-image-store.s3.amazonaws.com/0/208873/4676ff24-73c8-a57d-a29d-7ea20666278d.png)

## トリガー設定(Zabbix Server)
`GREEN`を表す `3`以外を障害と判断するように条件式を設定

![2018-08-22 22_40_16.png](https://qiita-image-store.s3.amazonaws.com/0/208873/1bfb9e2f-add0-c63f-db6d-d8063d887337.png)
THETA V単独でSkyWayを利用して360度映像を配信する

SkyWay-Android-SDKのp2p-videochatがTHETA V上で動かないか興味本位で試してみました。

結果としてはTHETA V上でp2p-videochatを動かし、通話相手に360度映像を流すことができました。
\# 謝辞で詳しく述べますが、最初は無理だと挫折していたのをgogoroyaさんに助言いただきできました
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">自分はTHETAPluginでSkyWay-Android-SDKをして音声・映像流せる事確認できてる。<a href="https://twitter.com/hashtag/skyway?src=hash&amp;ref_src=twsrc%5Etfw">#skyway</a> <a href="https://twitter.com/hashtag/thetaplugin?src=hash&amp;ref_src=twsrc%5Etfw">#thetaplugin</a> <a href="https://twitter.com/hashtag/webrtcjp?src=hash&amp;ref_src=twsrc%5Etfw">#webrtcjp</a><a href="https://t.co/9hw2J47269">https://t.co/9hw2J47269</a> <a href="https://t.co/lZjWo962Pc">https://t.co/lZjWo962Pc</a></p>&mdash; gogoroya (@gogoroya) <a href="https://twitter.com/gogoroya/status/1032685694487937024?ref_src=twsrc%5Etfw">2018年8月23日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

![screenshot-1535163712642.jpg](https://qiita-image-store.s3.amazonaws.com/0/123187/3d157881-6262-7e4b-f665-6fd24a31b88a.jpeg)

# 環境
SkyWay-Android-SDK: [v1.04](https://github.com/skyway/skyway-android-sdk/tree/v1.0.4)
RICOH THETA Plug-in SDK: [v1.0.0](https://github.com/ricohapi/theta-plugin-sdk/tree/v1.0.0)

THETA V: 2.40.2

Android Studio: 3.1.3
OS: Windows10 バージョン18.03

# 手順

[こちら](https://qiita.com/yokazuya/items/cda20420ee0b1b58e03f)の手順を参考に、以下リポジトリをビルドしたAPKをインストールする
https://github.com/masaue/skyway-android-sdk
\# gogoroyaさんのリポジトリでもOK
https://github.com/goroya/skyway_theta_plugin_example

# p2p-videochatの変更点

https://github.com/masaue/skyway-android-sdk/pull/1

- SkyWay-Android-SDKへRICOH THETA Plug-in SDKを追加する
 - これに付随して、SkyWay-Android-SDK側のbuild.gradleなどをRICOH THETA Plug-in SDKに合わせる
- SkyWay-Android-SDKからカメラを制御できるよう、onCreate()でその旨のIntentを投げる
 - Intentの仕様などは[こちら](https://api.ricoh/docs/theta-plugin-reference/broadcast-intent/#notifying-camera-device-control)を参照のこと
- startLocalStream()で、カメラの初期化を行なう

# 謝辞
[gogoroya](https://twitter.com/gogoroya)さんのおかげで不足していたカメラの初期化処理に気づき本記事を書くことができました。本当にありがとうございます。
【基礎から学ぶ Vue.js】Chapter9「ネストされた複雑なページを作成しよう」の動作確認 

#データの共有にはVuexを使用する（P304）
Vue.jsの名著【基礎から学ぶVue.js（通称：猫本）】のChapter9にある「データの共有にはVuexを使用する」の項目ではまってしまい、著者のmio様から直々にご教授いただきました内容の記録です。
いち読者のために、懇切丁寧にレクチャーしてくださったmio様に感謝です。

##反省：vuexモジュールの使い方を理解できてなかった
ど素人なのに、何となく読み進めてしまったため、Chapter8のVuexの使い方をしっかり理解していないでただ[サポートページ「S52 ネストされた複雑なページを作成」](https://cr-vue.mio3io.com/guide/chapter9.html#s52-%E3%83%8D%E3%82%B9%E3%83%88%E3%81%95%E3%82%8C%E3%81%9F%E8%A4%87%E9%9B%91%E3%81%AA%E3%83%9A%E3%83%BC%E3%82%B8%E3%82%92%E4%BD%9C%E6%88%90)だけを頼りに四苦八苦してました。
VueRouterで作るプロダクトでページ遷移が必要な場合、データの持ち回りにVuexが重宝されるためChapter8とChapter9はセットで確実に理解しなければいけませんでした。

##ポイント：モジュールとストアルートのアプリケーションへの登録
Vuex と Vuex モジュールを使用するために書籍のサンプルコードに加えて次の手順が必要です。

1. 「src/store/product.js」モジュールを「src/store.js」ファイルでストアルートに登録する（P.270～）
1. 「src/store.js」のストアルートを「src/main.js」のアプリケーションに登録する（P.256）

##コードの具体例
具体的には以下のコードの追記が必要です。
（書籍のサンプルコードで使われているディレクトリ構造を踏襲した場合）

###Vuexモジュールをストアルートに登録（src/store.js）
    import Vue from 'vue'
    import Vuex from 'vuex'
    import product from '@/store/product.js' // モジュールをストアルートに登録
    Vue.use(Vuex)

    export default new Vuex.Store({
      modules: {
        product // モジュールをストアルートに登録
      },
      //...
    })

###ストアルートをアプリケーションに登録（src/main.js）
    import Vue from 'vue'
    import store from './store.js'
    import App from "./App";
    import router from './router.js'

    new Vue({
      el: '#app',
        store, // アプリケーションに登録
        router,
        render: h => h(App)
      // ...
    })

##まとめ
Vuexの章のあたりから理解があやしくなり、そのまま読み進めた結果変なところでつまづいてしまいました。
[サポートページ](https://cr-vue.mio3io.com/)が懇切丁寧に説明されているため、しっかり理解せずにコピペで理解したつもりになってしまうと私と同じようなことになってしまうと思います。
あまりいないかもしれませんが、もし同じところでつまずいている方の助けになれば幸いです。

最後に、大変お忙しいところを私のようなど素人にも呆れずに大変丁寧なご対応をしてくださった著者のmio様に改めて感謝の意を表したいと思います。
ありがとうございました！
【Androidアプリ】ターゲットAPIレベルを26にしたら、FileUriExposedExceptionが発生してクラッシュした

# 前置き

> 2018 年 11 月: 既存のアプリのアップデートで、ターゲット API レベル 26 以降が必須になります。
【引用元】[Google Developers Japan: 今後の Google Play でのアプリのセキュリティおよびパフォーマンスの改善について](https://developers-jp.googleblog.com/2017/12/improving-app-security-and-performance.html "Google Developers Japan: 今後の Google Play でのアプリのセキュリティおよびパフォーマンスの改善について")

今後もアップデートしていくに辺り、AndroidアプリのターゲットAPIレベルを26に引き上げました。
しかし、アップデートしてからAndroid Vitalsを見て、対応漏れに気づいたことが1つありました。

それが本記事のFileUriExposedExceptionです。
調べていくと、本来であればAndroid7.0(ターゲットAPIレベル24)で対応すべき内容でした。

> Android 7.0 向けのアプリでは、Android フレームワークにより、自身のアプリ外への file:// URI の公開を禁止する StrictMode API ポリシーが適用されます。ファイル URI を含むインテントがアプリからなくなると、FileUriExposedException 例外によりアプリはエラーになります。
> アプリ間でファイルを共有するには、content:// URI を送信して、この URI への一時的なアクセス パーミッションを付与する必要があります。このパーミッションを付与する最も簡単な方法は、FileProvider クラスを使用することです。
【引用元】[Android 7.0 の動作の変更点 &nbsp;|&nbsp; Android Developers](https://developer.android.com/about/versions/nougat/android-7.0-changes?hl=ja#perm "Android 7.0 の動作の変更点 | Android Developers")

ということで、FileProviderクラスを使った実装に修正しました。

# FileUriExposedException例外対応

## 共有ディレクトリを定義するXMLの作成

```xml:app/res/xml/paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="album"
        path="." />
</paths>
```

## AndroidManifest.xmlにFileProviderクラスを定義する

```xml:AndroidManifest.xml
...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/paths" />
        </provider>
    </application>
</manifest>
```

## FileProviderクラスを使った実装に修正する

```java:xxxActivity.java
File file = new File(pathString);

Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);

Uri uri;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
    uri = Uri.fromFile(file);

} else {
    uri = FileProvider.getUriForFile(xxxActivity.this, BuildConfig.APPLICATION_ID + ".fileprovider", file);

}
intent.setDataAndType(uri, "image/*");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
        | Intent.FLAG_GRANT_READ_URI_PERMISSION
);

startActivity(Intent.createChooser(intent, "アプリケーションを選択"));
```

# 参考
[読書尚友のAndroid 7.0対応について - hishidaのblog](http://d.hatena.ne.jp/hishida/20170510/p1 "読書尚友のAndroid 7.0対応について - hishidaのblog")
[Android 画像ファイルを扱う際のFileとUriまとめ](https://qiita.com/wakamesoba98/items/98b79bdfde19612d12b0 "Android 画像ファイルを扱う際のFileとUriまとめ")
Rails: 既にレコードが存在しているテーブルに新たにnull falseなカラムを追加する時の挙動について

#概要
Railsの既にレコードが存在しているテーブルにnull falseを指定したカラムを追加したいと思った時の挙動について。

# 結論
null: false　に加えて default 
を指定してあれば、既に存在しているレコードにはdefault値がセットされるため、マイグレーションでカラムを追加してもエラーになりません。

## 実行内容
マイグレーションファイル内容

```
class AddColumnToUser < ActiveRecord::Migration[5.1]
  def change
    add_column :users, :send_status, :integer, limit: 2, default: 0, null: false, comment: '送信ステータス 0:送信前, 1:送信済, 2:送信失敗'
  end
end
```

## 実行結果
miagration実行前のテーブルのレコード

```
+----+------------+-----------------+---------------------+--------+------------+------------+--------------+---------------------+---------------------+-------------+
| id | account_id | lock_version | created_at | updated_at 
+----+------------+-----------------+---------------------+--------+------------+------------+--------------+---------------------+---------------------+-------------+
|  1 |  722672863 |  1 | 2018-08-21 10:22:24 | 2018-08-21 10:48:57 
|  2 |  722672863 |  0 | 2018-08-21 11:00:23 | 2018-08-21 11:00:23 　
+----+------------+-----------------+---------------------+--------+------------+------------+--------------+---------------------+---------------------+-------------+

```



migration実行後のテーブルのレコードの状態

```
+----+------------+-----------------+---------------------+--------+------------+------------+--------------+---------------------+---------------------+-------------+
| id | account_id | lock_version | created_at | updated_at |send_status |
+----+------------+-----------------+---------------------+--------+------------+------------+--------------+---------------------+---------------------+-------------+
|  1 |  722672863 |  1 | 2018-08-21 10:22:24 | 2018-08-21 10:48:57 | 0 |
|  2 |  722672863 |  0 | 2018-08-21 11:00:23 | 2018-08-21 11:00:23 | 0 |
+----+------------+-----------------+---------------------+--------+------------+------------+--------------+---------------------+---------------------+-------------+

```


### 環境情報
```
CentOS Linux release 7.4.1708 (Core) (さくらvps)
ruby: 2.4.3(rbenv)
rbenv 1.1.1-28-gb943955
rails 5.0.6
Phusion Passenger 5.2.3
Apache/2.4.6 (CentOS)
Capistrano 3.3.5
```
MongoDBのindexをターミナルから確認する方法

## 個人的メモ

- mongoシェルでDBに貼られたindexを確認する方法

```ruby
# mongoシェルをターミナルで起動
> mongo
MongoDB shell version: 3.2.11
connecting to: test

# db一覧を出す
> show dbs

# ローカル環境のdb一覧が出てくる
local                     0.000GB
mongoid_lab_development   0.000GB
mongoid_test       20.178GB

# mongoシェルで使用するdbを選択する
> use mongoid_test
switched to db mongoid_test

# db.コレクション名.getIndexes()でindexを表示する
# この場合のコレクション名はRailsアプリにあるモデル名と同じ(Userモデルならusers)
> db.users.getIndexes()
[
	{
		"v" : 1, # 1は昇順ソート
		"key" : {
			"_id" : 1 # idにindexが貼られている
		},
		"name" : "_id_", # indexの名前
		"ns" : "mongoid_test.users" #　ネームスペース
	}
]
```

## 最後に
普段、mongoidを使ってRailsアプリを作っているのですが、MongoDB自体のindexのことなどに不案内だったため、調べたメモとして投稿させて頂きました！
なるべく画面を黒くして目を疲れないようにしよう

# 内容

目が疲れるのでなるべく黒画面にするための方法

# 黒画面にした環境

windows7
Linux Mint LMDE2
word2016(windows版)
Vim
jupyter notebook
vivaldi

# はじめに

僕は長期間、いやそれ程長くなくても、白い画面をディスプレイで見ていると目が疲れてくる。なのでまず何でも黒い画面にしたくなるのだが、そんな僕のデスクトップを通りがかる会社の皆さんは、なんで君の画面はいつ見てもそんなに黒いのかねやばいサイトでも見ているのかねと言わんばかりにクスクスと通り過ぎていく。

…僕がおかしいのだろうか？そんなことはない、真夏に自転車に乗る時は日焼け防止のために紫外線カットのサングラスが必須だと聞いた、それとよく似ているはずだ。
というわけで、僕ができる限り行っている黒画面の方法を思いつくままに書いてみようと思う。

# windows7

これは下記の方法よりも万能なワイルドカード的方法だが、ウィンドウズ標準機能の拡大鏡を使う。
`win++`(ウィンドウズキーと"+"(プラス)キー同時押し)で拡大鏡のメニューが出せる。すると任意の拡大率で起動するが、すぐに`Win+-(マイナス)`を押せば等倍表示に戻る。この際、オプションから「色反転を有効にする」をチェックしていれば反転表示となる。

全ての場面で有効なワイルドカードではあるが、Aeroが使用可能なPC、またAeroが有効なテーマを使用している必要がある。また、僕の環境では少し描画が重いように感じる。そして、下記の他ソフトで独自に白黒反転していると逆に白くなってしまうので、僕は最後の手段として使用している。
ちなみにandroidは白黒反転機能が標準的に用意されているのでとても便利。

# vim

これはお馴染molokaiなどcolorschemeを使用しよう。

```vim:_gvimrc
colorscheme molokai
```

`~/.vim/colors/molokai/molokai.vim`のように置く。

# pdf閲覧

[evince](https://wiki.gnome.org/Apps/Evince/Downloads)がお勧め。文字だけでなく図も白黒反転してくれる。そして素晴しいところは、Ctrl+iで反転切り替えができるから。Okularも反転はできるのだがショートカットキーがなかった。pdfを閲覧している時は、図などで反転ではイメージできない時があるので随時切り替えたくなる。そのような時にショートカットキーがあるのとないのでは雲泥の差だ。
またLinuxでも標準的に使用可能なのもよい。windows版はmsys2などを経由してインストールするのがよいようだ。[こちら参考](http://www.yamamo10.jp/yamamoto/wordpress/?p=842)。

# word

上記の拡大鏡で実現するのに気付く前に採っていた方法は、ワードのメニューで、「デザイン→ページの色」で濃い目の色を選ぶと白黒反転するのを利用して、autohotkeyでショートカットキーを作成して実現していた。

```autohotkey
;バックグラウンドの色を青に
#b::
IfWinActive, ahk_exe WINWORD.EXE
{
  send, !gpc
  sleep, 100
  send,{down}{down}{down}{down}{down}
  send,{right}{right}{right}{right}
  send,{enter}
  }
  return
  
;バックグラウンドの色を白に
#w::
IfWinActive, ahk_exe WINWORD.EXE
{
  send, !gpc
  sleep, 100
  send,n
  }
  return
```

注意点は、文字の色が「自動」で設定されていないと反転してくれないので、そのような文字が多い時は素直に諦めて拡大鏡を使用するか、全ての文字を選択して自動に設定しなおす。もちろんこの場合は色が全部同じになってしまい困る場合もあるだろう。

# jupyter notebook

ipython notebookの時は凄く苦労したのだが、今は[jupyter themes](https://github.com/dunovank/jupyter-themes)を入れるのがとても楽チンでよい。

```bash
pip install jupyter-themes
jt -t molokai
```

molokai以外にも黒くてかっこいいのはあるので、そちらも試してみよう。

# vivaldi

[change colors](https://chrome.google.com/webstore/detail/change-colors/jbmkekhehjedonbhoikhhkmlapalklgn)がおすすめ。
vivaldiというかchrome系ブラウザなら使えると思うのだが、cssを上書きすることのできるプラグイン。上書きのオン/オフを、ショートカットキーに割り当てることができるのでとてもいい。書き換えた後の背景、文字の色はオプションから自分で指定できる。

# 最後に

やっぱ目はいたわらなきゃ！
JavaScriptのPromiseを説明しようぜ☆（＾ｑ＾）

# だらだらと書く。

async/await を使えだぜ。Promise を簡単にしたやつだぜ。
だが レガシーのリプレースマンは両方知っておく必要があるはめになる。 async/await、Promise の両方を説明する。

コードは試してないが　思い出して書くと、

```js
let promise = new Promise((resolve, reject) => {
    resolve();
});
```

こんな感じで Promise オブジェクトを作る。すると、

```js
// パターン１
promise
.then(() => {
},
err => {
});
```

と書くか、

```js
// パターン２
promise
.then(() => {
})
.catch(err => {
});
```

といったように書いて使う。

- パターン１は　then に対応したエラー処理を書きたいとき。
- パターン２は　エラー処理を１回で済ませたいとき。

につかう。エラーは ```reject(new Error('エラーメッセージ'));``` のように書いて使う。

まだ続く。

# thenチェーン

```js
promise
.then(() => {
    return new Promise((resolve, reject) => {
        resolve();
    });
})
.then(() => {
})
.catch(err => {
});
```

.then の中で プロミスを返すと、.then の返り値は Promise なので
.then をつなげることができる。

Promiseコンストラクターの引数に渡しているコールバック関数は、
制御が抜けてもブロックしていて、resolve() か、 reject() が実行されるまで
ブロックしている。

# resolve()の引数は、.thenのコールバック関数の引数に渡される。

```js
promise
.then(() => {
    return new Promise((resolve, reject) => {
        // ここで引数を１つだけ渡せる。オブジェクトにするとお得。
        resolve({
            name: 'わはは',
            age: 49
        });
    });
})
// resolve で渡された内容はこの result に入っている。
.then((result) => {
    console.log('name: ' + result.name + ' age: ' + result.age);
})
.catch(err => {
});
```

こんな気分。

# プロミスの配列をイテレートする。
Promise.all() 関数と、 Promise.race() 関数がある。はしょって all の方だけ説明する。

```js
let promiseArray = [];
// promiseArray 配列に、豪快に Promise をいっぱい追加するとする。

Promise.all(promiseArray)
.then((resultArray) => {
    // promiseArray が全部終わったらここにくる。
    // resultArray は、プロミスの配列。promiseArray と同じ順序で入っている。
})
.catch(err => {
});
```

１００個ぐらい SQL叩きたいときとか、 .then を 100個もつなげたくないんで、
Promise.all() を使えだぜ。 all の返り値も Promise。



# async/await の使い方。

- 条件1. await を使っている関数の頭には async とつける。

```js
### 例1
async function () {
    let returns = await func1();
}

### 例2
async () => {
    let returns = await func1();
};
```

頭に async を付けた関数は Promise インスタンスを返すようになる。つまり、

```js
### これと
async () => {
    return 'あいうえお';
};

### これは 同じ。
() => {
    return new Promise((resolve, reject) => {
        resolve('あいうえお');
    });
};
```

async の方が見やすいぜ。

- 条件2. Promise オブジェクトの頭には await を付けれる。

```js
### 例。
let returns = await new Promise ((resolve, reject) => {
    return 'あいうえお';
});

### 以下のコードと同等。
new Promise ((resolve, reject) => {
    resolve('あいうえお');
})
.then((returns) => {
});
```

await は、 .then( ) の代わりをする。

- 条件3. reject(err); の代わりに throw err; を使う。

```js
### 例
try {
    let returns = await new Promise ((resolve, reject) => {
        if (/*エラーが起こった時*/) {
            throw new Error('エラー');
        } else {
            return 'あいうえお';
        }
    });
} catch (err) {
    /* エラー処理 */
}

### 下のコードと同等。
new Promise ((resolve, reject) => {
    if (/*エラーが起こった時*/) {
        reject('エラー');
    } else {
        result('あいうえお');
    }
})
.then((returns) => {
})
.catch((err) => {
    /* エラー処理 */
})
;
```

try - catch 構文の方が、ネストが少なく見やすい。

- resolve(x); の代わりに return x; を使うが、ただし、関数を抜けるときの暗黙の return はブロックしないので　制御が抜け落ちてしまう。 これを防ぐには、  
関数の中の非同期部分を全部 await に書き換えたタイミングで new Promise((resolve,reject) => {}); の囲いを外していくといいだろう。
Chocolateyを使ってWindowsでパッケージ管理する

# Chocolateyを使ってWindowsでパッケージ管理する

# はじめに
LinuxのaptやyumのようにWindowsでもコマンドでソフトウェアのパッケージ管理を行う。

# パッケージ管理の利点
* インストーラを取ってきてGUIで次へ次へとやらなくて良くなる
* 複数台のWindows PCでのソフトウェアのインストール状況（パッケージやバージョン等）が合わせられる

# インストール方法
公式サイト参照
https://chocolatey.org/install

## ダイレクト接続でコマンドプロンプトでインストール
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

## プロキシ環境でのインストール方法
1. セットアップスクリプトのダウンロード
```
https://chocolatey.org/install.ps1
```
2. powershellを管理者権限で実行する
3. 以下のコマンドをpowershellで叩いてスクリプトを実行可能にする
```
Set-ExecutionPolicy RemoteSigned
```
4. プロキシを通す(IPとポートは自分の環境で置き換える)
```
$env:chocolateyProxyLocation = 'http://serverip:port'
```
5. シェルを実行する
```
.\install.ps1
```

# ソフトウェアのインストール方法
インストールが終わったら、管理者権限で実行されたpowershellもしくはコマンドプロンプトでコマンドを打つことでソフトのインストールが行えます。

```
choco install package_name -y
```

例えば、git for windowsのインストールは以下。

```
choco install git.install -y
```

## GUIフロントエンドの利用
コマンドを打つのは、インストールしたいソフトが明確なときは便利なのですが、そもそもどんなソフトがあるのかわからないし、名称もわからない場合は検索します。
GUIのフロントエンドを利用するのが便利なので、以下のコマンドで導入しておきましょう。

```
choco install chocolateygui
```

インストールが完了するとスタートメニューからChocolatey GUIを選択すると画像のようなGUIソフトが起動します。

![GUI操作](https://qiita-image-store.s3.amazonaws.com/0/99189/28548f33-3c41-df2d-d987-ce715715385e.gif)

1. chocolateyをクリックするとソフトの一覧が取得される
2. 一覧から選択するか、検索で絞り込んでインストールしたいソフトを選択する
3. インストールする

なれるまではGUIで検索して、一個ずつインストールしていくのが楽だと思います。

# ソフトウェアの更新
以下のコマンドでchocolateyでインストールしたソフトを一括更新してくれます。

```
cup all -y
```
git for windowsは頻繁に更新されるのでその度にインストーラをポチポチするのが、コマンド一発で更新されるのはかなり便利だと思います。

# GUIを使ってインストール済みのパッケージの一覧を出力
GUIを使うと導入済みのパッケージの一覧をconfigファイル(xml形式)に出力できます。
画像のボタンを押すことで出力されます。
![chocolateyGUI.jpg](https://qiita-image-store.s3.amazonaws.com/0/99189/6f5b66a6-0b11-06b6-2e20-e59290d29d39.jpeg)

chocolateyはconfigファイルを使ってパッケージの一括インストールができます。
なので、エクスポート機能で出力したconfigを別PCに移して一括インストールをすることで複数台のPCにパッケージを簡単に導入できます。

## xmlからの一括インストール
list.configというファイルを使って一括インストールするコマンド

```
choco install list.config
```
# installとportableのどちらを選択するか
パッケージを検索していると同じパッケージでも(Install)と(Portable)とついているのを見かけると思います。

[github](https://github.com/chocolatey/choco/wiki/ChocolateyFAQs#what-distinction-does-chocolatey-make-between-an-installable-and-a-portable-application)によると違いはインストーラーがあるかないかのようです。

普段インストーラーでProgram Filesにインストールしているものはinstallを選択するとよいと思います。
portableだとc:\ProgramData\chocolatey\libに実行ファイルが展開されるようです。

exeと同じディレクトリにini等の設定ファイルや、作業フォルダを作るようなものはportableを選ぶと良いでしょう。
VirtualStore機能でハマるのを回避できると思います。

例えばTomcatは設定や公開用のフォルダがデフォルトでexeと同じディレクトリに作成され、Program Filesにインストールするのはあまりよい選択ではありません。
portableはありませんでしたが、オプションで指定することでインストール先を変更できるようです。

```
choco install tomcat -params "unzipLocation=*path*"
```

# ChocolateyToolsLocationを設定する
[chocolatey doc](https://chocolatey.org/docs/helpers-get-tools-location)によると、Program Filesにインストールするのが適切でないソフトは、環境変数ChocolateyToolsLocationで指定したディレクトリにインストールされるようです。
この種類のソフトは、環境変数が作られていないと自動でc:\toolsに設定されて、c:\toolsにインストールされます。

cmderがこれに該当していました。

インストーラなしのソフトのインストール先を自分で固定している場合は、そのディレクトリをChocolateyToolsLocationに指定しておくと良いでしょう。
Pythonインストールメモ - 3.6.6(64bit)

# インストーラの入手
Windows 64bit版のパッケージを入手
https://www.python.org/downloads/windows/
「Download Windows x86-64 executable installer」から入手
※matplotlib がまだ3.7.0に対応していなかったため、3.6.6にした（2018/7/9時点）

# インストール
## インストーラ起動
- [Add Python 3.6 to PAHT] にチェック
- [Customize Install] を選択

![image.png](https://qiita-image-store.s3.amazonaws.com/0/283233/eb49c67c-8ee8-951d-0d8b-cc46d16b207f.png)


## Optional Features
デフォルトのまま

![image.png](https://qiita-image-store.s3.amazonaws.com/0/283233/182f971d-fb58-bba0-ede0-e67795ccdb85.png)

## Advanced Options
- [Install for all users] にチェック

![image.png](https://qiita-image-store.s3.amazonaws.com/0/283233/a8d5363a-636d-71fd-cde7-fc6a11ddcb14.png)

以上
.gitを消してもuser.emailとuser.nameは残るので注意

組み込み系のLinuxを使っている人は注意してください。


```shell
# .git/ディレクトリを削除  
$ rm -r .git

# git configすると、user.emailとuser.nameは残っている
$ git config -l
core.editor=nano
user.email=tanaka@abc.co.com
user.name=tanaka

# この状態では、設定変更もできません
$ git config --global user.email "dammy@example.com"
error: could not lock config file .git/config: そのようなファイルやディレクトリはありません

# なので、一旦git initします
$ git init
Initialized empty Git repository in /.git/

# 変更できるようになるので適当な設定値で上書きします
$ git config --global user.email "dammy@example.com"
$ git config --global user.name "dammy"

# .git/ディレクトリはもう必要ないので消します
$ rm -r .git

# 上書きできてるか確認します
$ git config -l
core.editor=nano
user.email=dammy@example.com
user.name=dammy
```


# 追記
<b>コメントで指摘がありましたので、記事を追記しました。コメントありがとうございます。</b>

コメントでご指摘いただいたとおり、--globalでユーザー毎の設定をした場合は、"$HOME/.gitconfig"に設定値が書かれていますので、それを編集する方法もあります。
たとえば以下のような状況を考えます。

```shell
# リポジトリの初期設定
$ git init

# --localの設定
$ git config --local user.email localman@co.com
$ git config --local user.name localman

# --globalの設定
$ git config --global user.email globalman@co.com
$ git config --global user.name globalman

# --systemの設定
$ git config --system user.email systemman@co.com
$ git config --system user.name systemman
```

この状態で、それぞれの設定を削除する方法を考えます。


# --localの設定
--localの設定はリポジトリ毎に管理され、.git/configに保存されます。つまり.gitディレクトリを消したら--localの設定は削除できます。

```shell
# .gitディレクトリを削除する
$ rm -r .git

# 設定の確認（localの設定は消える）
$ git config -l
user.email=systemman@co.jp
user.name=systemman
core.editor=nano
user.email=globalman@example.com
user.name=globalman
```


# --globalの設定
--globalの設定はユーザ毎の設定となります。なので.gitディレクトリを消しても--globalの設定は削除できません。

--globalの設定は"$HOME/.gitconfig"に保存されていますので、それを書き換えるか削除します。

```shell
$ vi $HOME/.gitconfig
[core]
        editor = nano
[user]
        email = globalman@example.com
        name = globalman
```


# --systemの設定
--systemの設定はシステム（OS）毎の設定となります。なので.gitディレクトリを消しても--globalの設定は削除できません。

--systemの設定ファイルの場所は、OSによって異なるようです。
Linux系などでは（私のRaspbian環境では）
・/etc/gitconfig
にあります。
 
一応Windowsについても言及すると、
・\$HOME\.gitconfig（大抵のユーザの$HOMEはC:\Users\$USER）
Git for Windows v2.x 以降を使っている場合は、
・C:\Documents and Settings\All Users\Application Data\Git\config（Windows XP）
・C:\ProgramData\Git\config（Windows Vista以降）
にあります。

上記の設定ファイルを書き換えるか削除します。当然書き込み権限が必要になります。

```shell
$ vi /etc/gitconfig
[user]
        email = systemman@co.jp
        name = systemman
```

# 参考URL
<a href="https://qiita.com/masmatsum/items/da780bed0472bfd74fa8">
Git for Windows の設定ファイルの場所</a>
<a href="https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup">1.6 Getting Started - First-Time Git Setup</a>
(社内勉強会) API用Webフレームワークの構築・調査

## 目的
プロダクトに適したAPI用Webフレームワークの導入のための調査

## 現状
flaskを利用してAPIを構築しているが、要件が膨れ上がり複雑度を増してきている
生産性を高く保つために、FWの乗り換えを検討している

## 作業概要
各FWについて以下の観点でプロダクトにマッチしているかを調査する

- 必要な機能が揃っている、しかし不要なものがない
- メンテナンス性が高い（描きやすく読みやすい）
- ルールや規約が整備され、迷うことが少ない

社内勉強会にて、一人1FWを調査し、調査結果を持ち寄り発表する

## 作業詳細
### 1. シンプルなAPIの作成
TODOアプリのAPIを作成してみる

#### endpoint
- GET /todo (SELECT)
- POST /todo (INSERT)
- PUT /todo/<id> (UPDATE)
- DELETE /todo/<id> (DELETE)

#### TODO's data Model
- id (サロゲートキー、PK)
- message
- created_time
- updated_time

### 2. 各APIの機能有無について調査
以下の22の観点についての対応状況を調査
https://qiita.com/tmknom/items/08b69594e32a92bccee5#%E8%A8%80%E8%AA%9E%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E9%81%B8%E5%AE%9A

### 対象Webフレームワーク
LLを中心に選定。Javaは生産性の観点で今回は除外
- Ruby: Rails(APIモード)
- PHP: Laravel(Lumen)
- Python: Django(Django REST Framework)
- Python: Pyramid
Go Ginなどあと３つ追加予定

## おまけ
Google Trendによる比較
https://trends.google.co.jp/trends/explore?date=all&q=java%20spring,php%20laravel,ruby%20on%20rails,django%20python
コードで UIButton と UIBarButtonItem のタップイベントを発生させる

`UIButton` の継承元の `UIControl` には以下のメソッドがあるので普通にできる

```
let button = UIButton()
button.sendActions(for .touchUpInside)
```

`UIBarButtonItem` は `UIControl` を継承していないので
割とハマっていたのだが `Perform Selector` を使えばできるらしい

```
let barButtonItem = UIBarButtonItem()
_ = barButtonItem.target?.perform(barButtonItem.action, with: nil)
```

以前の記事だと使えなかったらしいが今は大丈夫なんでしょうか…
https://qiita.com/takuyaaan/items/a62aa583e91f1a3509da
RubyでGoogleのCloud Translation APIを使ってみる

今回は文章から言語の種類を検出して、日本語に翻訳するスクリプトを書いてみます。

APIのキーはGoogle Cloudのプロジェクトの```認証情報```から適当に発行して有効にしてください。

```ruby:translate.rb
require 'net/http'
require 'uri'
require 'json'

# 言語の種類を検出するメソッド
def lang_data(context)
  url = URI.parse('https://translation.googleapis.com/language/translate/v2/detect')
  params = {
      q: context,
      key: "GOOGLE-CLOUD-API-KEY"
  }
  url.query = URI.encode_www_form(params)
  res = Net::HTTP.get_response(url)
  json = res.body
  # レスポンスのjsonの言語のパラメータをパースする
  JSON.parse(json)["data"]["detections"][0][0]["language"]
end

def translate_to_japanese(context)
  url = URI.parse('https://www.googleapis.com/language/translate/v2')
  params = {
      q: context,
      target: "ja", # 翻訳したい言語
      source: lang_data(context), # 翻訳する言語の種類
      key: "GOOGLE-CLOUD-API-KEY"
  }
  url.query = URI.encode_www_form(params)
  res = Net::HTTP.get_response(url)
  json = res.body
  # レスポンスのjsonの言語の翻訳結果の部分のパラメータをパースする
  "Japanese Result:#{JSON.parse(json)["data"]["translations"].first["translatedText"]}"
end

puts translate_to_japanese("I want to drink something.")
```
手軽にAPIが扱えていいですね。料金も非常にお手軽なのでぜひ試してみてください
# 参考にしたページ

- 翻訳部分:https://cloud.google.com/translate/docs/translating-text?hl=ja

- 言語検出部分:https://cloud.google.com/translate/docs/detecting-language?hl=ja
Ruby on Railsで”undefined method `each' for nil:NilClass”エラーが出た時の対処法

#環境・状況

* AWS上のCloud9
* Ruby on Rails
* Udemyの[Web開発入門完全攻略コース - プログラミングをはじめて学び創れる人へ！未経験から現場で使える開発スキルを習得！](https://www.udemy.com/web-application-development/)
* 「レクチャー２２4　一覧画面の動作確認」　にて

#症状
構築した画面の動作確認にて下記エラー発生

```
NoMethodError in Tasks#index
Showing /home/ec2-user/environment/rails_projects/todo/app/views/tasks/index.html.erb where line #3 raised:

undefined method `each' for nil:NilClass
Extracted source (around line #3):             
１　<h1>ToDoアプリ</h1>
２　<ul>
３  　<% @tasks.each do |task| %>
４    　<li>
５      　<%= check_box_tag '','' %>
６      　<%= task.title %>
Rails.root: /home/ec2-user/environment/rails_projects/todo
```
エラー部分は

```
undefined method `each' for nil:NilClass
```


#原因
繰り返し処理の対象である`＠tasks`の中身が`nil`である。

#解決策

コントローラーファイルである`Tasks_controller.rb`内のスペルミス

```
class TasksController < ApplicationController
  def index
    @taskes = Task.all
　　　^^^^^^ ※”Tasks”ではなく”Taskes”とスペルミス。
  end
end
```

#参考
[エラーfor nil:NilClassについて](https://teratail.com/questions/3803)
>nil（他の言語ではnullということも多い、「何もない」という特殊なオブジェクトです）に対してメソッドを実行しようとすると、表記のような「NilClassにメソッドがない」旨のエラーになります。
PolymerでFirebaseのリアルタイムデータベースとデータのやり取りをする

#データベースを有効にする

Firebaseにアクセス [こちら](https://firebase.google.com/)

**Database**をクリック

**Realtime Database**から**データベースを作成**をクリック

- ロックモード
- テストモード

から、**テストモード**を選択して、**有効にする**をクリック

#Polymerでデータ送信用のエレメントをつくる

##コンポーネントのインストール

###paper-input

paper-inputは [こちら](https://www.webcomponents.org/element/PolymerElements/paper-input)

**DOWNLOAD**のコマンドをクリックしてコピー
ターミナルにペーストしてインストール

###paper-button

paper-buttonは [こちら](https://www.webcomponents.org/element/PolymerElements/paper-button?bower)

**DOWNLOAD**のコマンドをクリックしてコピー
ターミナルにペーストしてインストール

##テキスト入力欄と送信ボタンを作成

ダウンロードした**paper-input**と**paper-button**を
src/my-view1.htmlにインポート

```html
<link rel="import" href="../bower_components/paper-button/paper-button.html">
<link rel="import" href="../bower_components/paper-input/paper-input.html">
```

`<div class="card"></div>`の中身を書き換える

```html
<div class="card">
  <paper-input label="name" id="name"></paper-input>
  <paper-button raised on-click="submitName">submit</paper-button>
</div>
```

#データのやり取りは２種類

##データの書き込み

データベースの**name**というパスに、inputのvalueを書き込むには**set**を使います。
**set**は同じ場所に既にデータが存在する場合は、上書きされます。

```js
submitName() {
  const name = this.$.name.value
  window.firebase.database().ref(`name`).set(name)
}
```

##データを追加する

データベースの**name**というパスに、inputのvalueを**追加**したい場合は**push**を使います。
**push**によってデータが送信されると、自動的に**key**を付けて特定の場所にデータを追加してくれます。

```js
submitName() {
  const name = this.$.name.value
  window.firebase.database().ref(`name`).push(name)
}
```
Apache Struts2にリモートコード実行(RCE)の脆弱性(S2-057、CVE-2018-11776)

#はじめに
本日(8/22)、最新の[リモートコマンド実行脆弱性（S2-057）](https://cwiki.apache.org/confluence/display/WW/S2-057)が公開され、8/22の夜中にはPoCが公開されました。
~~脆弱な条件はいろいろあるみたいだけど、正確なのはJPCERT/CCだと思ってる。~~
検証の結果、やっぱりalwaysSelectFullNamespaceがTrueである必要があるみたいです。


# 脆弱性の概要(直訳)
名前空間を持たず、上位アクションにも名前空間を持たない/ワイルドカードを利用している場合、リモートでコードが実行される可能性があります。

# 影響範囲のバージョン
Struts 2.3 - Struts 2.3.34
Struts 2.5 - Struts 2.5.16
Strutsのサイトでは、サポート以前のバージョンは未確認とのことですが、検証した2.2系のもOGNLは解釈してくれました。

#脆弱性の条件
JPCERT/CCはalwaysSelectFullNamespaceに関して言及していませんが、OGNLの解釈を成功するためにはTrueにする必要があります。

【IPA】
1と2を両方満たす場合、脆弱である。
1.alwaysSelectFullNamespace を true に設定している場合
2．Struts設定ファイルに、オプションのnamespace属性を指定しないか、ワイルドカードネームスペースを指定する "action"タグまたは "url"タグが含まれている場合

【JPCERT/CC】
どれか満たせば、脆弱である。
・Struts の設定ファイル(struts.xml など) で namespace の値が指定されていない
・Struts の設定ファイル(struts.xml など) で ワイルドカードが指定されている
・URL タグの記述において value かaction の値が指定されていない

#検証結果
参考URLのPoCを参考に、特にalwaysSelectFullNamespaceに関する検証を実施しました。
結論として、strutsのデフォルト設定（alwaysSelectFullNamespaceはFALSE）では、OGNLが解釈されて、コード実行できました。

Strutsのデフォルト設定は、Strutsの/WEB-INF/lib 中の struts2-core-2.x.x.x.jar ファイルを展開し、org/apache/struts2/default.propertiesを見ることでわかります。

struts.xmlにalwaysSelectFullNamespaceをFALSEにすれば成功しませんでしたが、Strutsのデフォルト設定で成功したので、IPAが記載している成功条件のalwaysSelectFullNamespaceをTrueというのは違う気がしてます。(PoCも設定してませんしね)

struts.xmlにちゃんとalwaysSelectFullNamespaceをFALSEと書いたら成功しないので、対策としてはちゃんと指定するといったところでしょうか。

(8/27追記)
showcaseには、struts2-convention-plugin-\*.\*.\*.jarというものは含まれています。
このjarを展開してやると、struts-plugin.xmlがあり、ここにalwaysSelectFullNamespaceがTrueと記載されておりました。
このxmlをFalseにしてやれば、コード実行は成功しませんでしたので、成功条件にはTrueが必要であることがわかりました。

PoCが成功すると、以下のようなURLにリダイレクトされます。
ただ、Strutsのバージョンによっては、サーバからの応答が302になり、次のアクセスが200だったり、404だったりするのがこまっちゃった。
ちなみに、自分は2.3.34のバージョンでコード実行できました。

リクエスト：
hXXp://192.168.220.137:8080/struts2.3.34-showcase/OGNL形式/actionChain1.action

リダイレクト先：
hXXp://192.168.220.137:8080/struts2.3.34-showcase/java.lang.UNIXProcess@347223c7/register2.action

#参考URL
[Security Bulletins S2-057](https://cwiki.apache.org/confluence/display/WW/S2-057)
[脆弱性発見者のブログ](https://lgtm.com/blog/apache_struts_CVE-2018-11776)
[IPA(Apache Struts2 の脆弱性対策について(CVE-2018-11776)(S2-057))](https://www.ipa.go.jp/security/ciadr/vul/20180823-struts.html)
[JPCERT/CC(Apache Struts 2 の脆弱性 (S2-057) に関する注意喚起)](https://www.jpcert.or.jp/at/2018/at180036.html)
[PoC(jas502n/St2-057)](https://github.com/jas502n/St2-057)
[中国語の解説サイト](https://xz.aliyun.com/t/2618) →Redirect actionだけでなく、Action chainingとPostback resultもあってわかりやすい


#最後に
中華系のブログ見る限り、ServletActionRedirectResult.javaに存在するnamespaceの値を渡すところが脆弱みたいです。やっぱりいつものOGNL形式！

8月25日18時現在も、ハニーさんで検知はありません。
今回の脆弱性は、struts使ってたら即脆弱ではないので、攻撃者もあまり使わないと思います。
そもそもそんな設定してんの？って話。

修正(8/25)
もろもろと検証結果を追加

修正(8/27)
[ぼんたさん](https://twitter.com/bontamoffu)より、struts2-convention-pluginに関する情報提供をいただきました。
ありがとうございました。
Carrierwaveで複数の画像をSQLiteのDBに保存する

以下のページの記載内容が前提
https://blog.otsukasatoshi.com/entry/2016/05/04/185133
https://github.com/carrierwaveuploader/carrierwave#multiple-file-uploads
https://qiita.com/ggtmtmgg/items/ba5f275c122c83013ea1

##はじめに
Ruby on Railsでウェブアプリを作る際、画像をデータベースに保存する処理が必要となった際はだいたいの人が「Carrierwave」を使うのではなかろうか。私もその一人で、導入自体は容易でしたが、複数画像をアップロードしようとして少しハマったので備忘録を兼ねて記事にします。

##インストール
Gemで容易にインストール可能なので割愛。

##DBについて
SQLiteを使うか、postgreSQLで扱いが異なり、postgreSQLについては上記サイト等多数のページで解説されているため、<strong>ここではSQLiteについてのみ言及します。</strong>

##カラムについて
SQLiteはpostgreSQLと違い<strong>JSON型のカラムに対応していないため</strong>、解説サイトどおりにやると詰まります。String型のカラムを用意しておきます（arrayにする必要はない）。

##Modelについて
```
class Post < ApplicationRecord
    mount_uploaders :images, ImageUploader
    serialize :images, JSON
end
```
`mount_uploaders :images, ImageUploader`は、PostモデルにCarrierwaveを関連付けている行です。複数画像の場合、`mount_uploader`ではなく`mount_uploaders`にすること。

`serialize :images, JSON`は、テキスト型のカラムに配列を格納するための行です。形式をJSON型にしています。つまり、データ自体はString型だけれども、その実態はJSONデータという訳です。

##DBへの保存
`<%= form.file_field :images, multiple: true %>`
実際のフォームの書き方です。`multiple: true`とし、複数のファイルを選択できるようにしています。

##DBからの読み込み
`@selectedPost.images`に、画像の（ルートから見た）相対パスが、画像の数を要素数とする配列として格納されています。

##おわりに
そもそもpostgreSQLを使えば詰まりませんでしたが、RailsのデフォルトがSQLiteで、postgreSQLにしようとしたらめんどくさくて、しかもpostgreSQLにするメリットが知識がなくわからないので、なるべくSQLiteで進めたかったためにちょっとハマってしまった訳です。プログラマーにとって怠惰は美徳と言われていた気がしますが、勉強はだいじだなぁとおもいましたまる
素のwindowsで簡単にbase32のランダムな8文字を作る方法

こんな文字列 
`wq20pudk.ei5`


win + x, c でコマンドプロンプトを起動する

```
> [system.io.path]::getrandomfilename()
```

cmd.exeの人は、

```cmd
> powershell -c "[system.io.path]::getrandomfilename()"
```

case-insensitiveなので全部小文字でもOK
import-moduleなしで呼べる

.NETの基本クラスライブラリ(BCL)にある`System.IO.Path.GetRandomFileName`
https://docs.microsoft.com/ja-jp/dotnet/api/system.io.path.getrandomfilename?view=netstandard-2.0#remarks

### base32

普通のbase32は
[wikipedia base32](https://ja.wikipedia.org/wiki/三十二進法)
[RFC4648 The Base16, Base32, and Base64 Data Encodings](https://tools.ietf.org/html/rfc4648#section-6)
a-z, 2-7, =

GetRandomFilenNameの結果のbase32は、小文字a-zと数字0-5

>https://source.dot.net/#System.Private.CoreLib/shared/System/IO/Path.cs,233
>
```c#
s_base32Char = {
                 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
                 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
                 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
                 'y', 'z', '0', '1', '2', '3', '4', '5'};
```
ガウシアン基底をプロットする

# 狙い
タイトルそのまま

# コード

```python
import matplotlib.pyplot as plt
import numpy as np

rng = np.random.RandomState(1)
x = 10 * rng.rand(500)

def multi_gauss(X, j, s=2):
    return np.exp(-(X - j)**2 / (2 * s **2))

for i in range(0,20):
    y = multi_gauss(x, i)
    plt.scatter(x, y, label=str(i));
```

# 結果
![image.png](https://qiita-image-store.s3.amazonaws.com/0/222554/3fb4437a-746b-c247-5258-849cca979c1a.png)
vid2vid を動かす(2018 年 8 月 22 日時点)

漢なら vid2vid で動画生成したいですね!

やりましょう!

できました.

<blockquote class="twitter-tweet" data-lang="en"><p lang="ja" dir="ltr">ねんがんの vid2vid の実行に成功したぞ!!!! 🎉🎉🎉🎉✨✨✨💮💮💯💯💯💯💯💯💯💯✨✨✨✨㊗️㊗️㊗️㊗️㊗️✌️✌️✌️✌️✌️✌️💪💪💪💪💪 しかしやるべきことたくさんあります. 優秀な vid2vid 若人を合法的なあらゆるどんな手段を使ってでも探し出す旅に出たい. 日々精進あるのみですね. <a href="https://t.co/xcfQaOYoq6">pic.twitter.com/xcfQaOYoq6</a></p>&mdash; Syoyo Fujita ⚡️ No ray tracing No life (@syoyo) <a href="https://twitter.com/syoyo/status/1032221494665854976?ref_src=twsrc%5Etfw">August 22, 2018</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 実行環境

* Ubuntu 16.04 + CUDA 9.0
* pytorch 0.4.1
* 1080 Ti

## 依存ライブラリのコンパイル

script を動かし, flownet2 をダウンロード, コンパイルします.

```bash
$ python ./scripts/download_flownet2.py
```

モデルを落とします.

```bash
$ python ./scripts/download_models.py
```

ダウンロードにしばらくかかりますので待ちます.

## 動かす.

README を参考にやりましょう.

```
$ ./scripts/test_2048.sh
```

Voila! vid2vid で画像が生成されました!


## TODO

* DensePose https://qiita.com/syoyo/items/e9193d18b0970950b9c6 とポーズ推定を組み合わせ, Tik Tok 映えダンス動画生成を極める.
* Quadro RTX 8 枚差しマシンで学習したい(論文によれば, 学習は V100(32 GB mem version?) x 8 で 10 日かかっている).
* 優秀な GAN 若人さまが, **人類史上最速で優秀な vid2vid 若人さまへ昇華** なされるスキームを確立する
Markdownのリンク記法 [TEXT](URL) を覚えるための図

手で書いてないとよく忘れるので、図で頭に刷り込む。

- TEXT という文字は四角っぽい
- URL という文字は丸っぽい

![image](https://user-images.githubusercontent.com/13635059/44459771-c7cf3580-a645-11e8-8a37-034190a88872.png)

![image](https://user-images.githubusercontent.com/13635059/44459782-cb62bc80-a645-11e8-927f-acdf8723df60.png)

![image](https://user-images.githubusercontent.com/13635059/44459785-ce5dad00-a645-11e8-9842-c6c6c9a17058.png)

## 書いてみよう

いちど手で書けば忘れにくいはず。

紙にでも、タブレットのお絵かきアプリでも。

![image](https://user-images.githubusercontent.com/13635059/44460139-fbf72600-a646-11e8-89b8-83db0064f6f1.png)


## Links

- [Gist](https://gist.github.com/YumaInaura/eaa2ebab449ee4984bebcadf2270bbbb/edit)
- [Medium—imported](https://medium.com/supersonic-generation/markdown-remember-link-syntax-text-url-with-picture-517d543aa327)








<!-- Update From Qiita API -->

# チャットメンバー募集


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

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





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
自作PCメモ

## 2016/03/03
| 種類 | メーカー | 型番 | 仕様 | 目安の価格（ベースからの差分という形なので正確ではない） |
| --- | --- | --- | --- | --- |
| CPU | Intel | Corei7 6700 | 4C8T / 3.4GHz / 65W / LGA1151 | 14904 |
| CPUクーラー | サイズ | APSALUS4-120 | 水冷 | 8980 |
| メモリ | Samsung | M378A1G43EB1-CPB | DDR4-SDRAM 8GB PC4-17000 2133MHz x 2枚 | 5800 |
| マザーボード | ASROCK | H170M-ITX/ac | mini-ITX / WiFiアンテナ付き | - |
| ディスク | Crucial | MX200 | SSD 500GB 2.5インチ | 12744 |
| ディスク | 東芝 | MQ01ABB200 | HDD 2TB 2.5インチ | 11120 |
| ビデオカード | ASUSTek | GTX970-DCMOC-4GD5 | メモリ4GB / ショートサイズ 170mm | 29800 |
| 電源 | ディラック | DIR-TCAXP-600 | 600W / 80PLUS / PLATINUM / ATX | 8424 |
| 筐体 | SilverStone | SST-SG13WB-Q | (W)222×(H)181×(D)285mm / 11.5L / ATX電源及び267cmまでのグラボを搭載可能 | - |

- ルンバに何度も激突されまくっていたらマザボが壊れて電源が入らなくなったことがある
- CPUクーラーは以下を比較して後者を選んだ
   - SSのTD03-LITE（18~35[dBA]）
      - https://www.silverstonetek.com/product.php?area=jp&pid=586
   - サイズのAPSALUS4 120（4.0~29.5[dBA]）
      - http://www.scythe.co.jp/cooler/apsalus4-120.html
- 電源は以下を比較して後者を選んだ
   - CORSAIR CS650M
   - ディラックのDIR-TCAXP-600
Python CascadeClassifier　エラー

症状
Pythonで顔認証をやるために、インターネットのサイトのサンプルコード通りにやったら、
SystemError: <class 'cv2.CascadeClassifier'> returned a result with an error set
というエラーが出る。

作業環境
Windows10 
Spyder(Python3.6)

#原因
githubのhaarcascade_frontalface_default.xmlをダウンロードして、読み込むとエラーになる。そのため、公式サイトのhaarcascade_frontalface_default.xmlファイルをダウンロードして、読み込んだら、成功しました。
（ファイルサイズが全然違う。githubの方はデータを追加していて、追加したデータがエラーとなったのかと個人的に思います）
参考にしたサイト
http://sh0122.hatenadiary.jp/entry/2017/10/30/210411

・上のタブからRELEASESをクリック。
・一番上の3.3.1のSourcesをクリック
・zipファイルがダウンロードされるので、任意の場所に保存
・任意の場所に解凍

以上のように、公式のカスケードファイルを使ったら、自分もうまくいきました。現在のバージョンだと、githubにあるカスケードファイルを使うとエラーになるということです。


##カスケードファイルをどこに置けばよいかわからない人へ
自分も最初迷ったのでメモ。自分の場合USBにWinPythonをインストールした。
Spyderを使った場合、初期状態のファイルは、
F:\WPy-3661\settings\ .spyder-py3\temp.py
にある。
spyder.exeのファイルは
F:\WPy-3661\Spyder.exe
にある。
絶対パスで指定したい場合

```
cascade = cv2.CascadeClassifier("F:/WPy-3661/haarcascade_frontalface_default.xml")
```
とでもすればよいと思う。

相対パスで指定したい場合

```
cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
```
このとき、haarcascade_frontalface_default.xmlのファイルは、
F:\WPy-3661\settings\ .spyder-py3\　のディレクトリに置けばよい。
GPSの研究　その42

#概要
gpsを理解したかった。
rtknaviでfixが見たかった。

#写真
![image](https://qiita-image-store.s3.amazonaws.com/0/18104/9811d060-3736-f438-eba5-602aa9b3e760.png)


#仕掛け

ローバーのubxを配信してくれている、奇特な方がおられます。
ありがたく、利用させてもらいました。

以上。
【GAS/VBA】任意のサイズの乱数表をワークシート上に生成する

ワークシート上に適当なデータを散らかしたい時ってありませんか？
私はあります。ので、そういう時に使えるスクリプトを作りました。

```javascript:Googleスプレッドシート
function RandTable() {
  tmp = Browser.inputBox('乱数表のサイズをカンマ区切りで入力してください').split(',')
  row = +tmp[0]
  col = +tmp[1]
  tgtCell = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getActiveCell()
  //処理をキャンセルできる
  if (Browser.msgBox(
      tgtCell.getA1Notation()+'から'+row+'行'+col+'列の乱数表を書き込みます',
      Browser.Buttons.OK_CANCEL) === 'ok') {
    rowArr = []
    for(var i=1; i<=row; i++) {
      colArr = []
      for(var j=1; j<=col; j++) {
        colArr.push(Math.round(Math.random()*100))
      }
      rowArr.push(colArr)
    }
    tgtCell.offset(0,0,row,col).setValues(rowArr)
  }
}
```

```visualbasic:Excel
Sub RandTable()
    Dim tmp As Variant
    tmp = Split(InputBox("乱数表のサイズをカンマ区切りで入力してください"), ",")
    Dim row As Long, col As Long
    row = tmp(0)
    col = tmp(1)
    Dim tgtCell As Range
    Set tgtCell = Selection
    ' 処理をキャンセルできる
    If (MsgBox(tgtCell.Address(0, 0) & "から" & row & "行" & col & "列の乱数表を書き込みます", _
        vbYesNo + vbInformation) = vbYes) Then
        Dim table() As Long
        ReDim table(1 To row, 1 To col)
        Dim i As Long, j As Long
        For i = 1 To row
            For j = 1 To col
                table(i, j) = Round(Rnd() * 100)
            Next
        Next
        tgtCell.Resize(row, col) = table
    End If
End Sub
```

Googleスプレッドシートの場合はカスタム関数にすることも出来ます。

```javascript:カスタム関数
function RandTableEasy(row,col) {
  rowArr = []
  for(var i=1; i<=row; i++) {
    colArr = []
    for(var j=1; j<=col; j++) {
      colArr.push(Math.round(Math.random()*100))
    }
    rowArr.push(colArr)
  }
  return rowArr
}
```

Excelはそろそろワークシート関数で配列の戻り値を受け取れるようになるんでしょうか？
戻るボタン（ブラウザバック）による　submit 2重実行を防ぐ


## *はじめに*  
タイトル通りです。
HTMLでsubmit実行後、別ページに遷移db値を登録をします。
登録完了後にブラウザの戻るを押すと再度submitが実行されて
2重にDBに登録されてしまう事象です。

google検索したのですが、意外な事に記事があんまりhitしませんでした。
解説記事が増えるということは、ユーザー側にはいいことなので記載します。


注）クリティカルな事象には向きません

## 動作確認環境
Windows 7(x64) 
Internet Exploere 11

## 使った物
javascript を使いました。  
HTML5の History API 

```addEventListener.js
<script type="text/javascript">
    history.pushState(null, null, null);

    window.addEventListener("popstate", function() {
        history.pushState(null, null, null);
    });
</script>  
```

### 動作結果
戻るボタンを押しても戻らなくなりました。

### 良い点
・chrome IE10,11 Firefox safari で利用可 

### 欠点
・本当に戻るボタンが効かなくなる「だけ」
・戻るボタンの見た目は活性化したまま 
・互換モードで<font color="MediumVioletRed">**IE9以前**</font>の場合は効かない 
・submitの2重投稿そのものを防いでいるわけではない


### 根本的な解決使えそうな資料ない？
@syobochim さんのスライドはいかがでしょうか。
>title:さいきょうの二重サブミット対策 
>https://qiita.com/syobochim/items/120109315f671918f28d 

<br>

### 参考資料
https://hidari-lab.hatenablog.com/entry/2015/03/02/212818 
https://developer.mozilla.org/ja/docs/Web/API/History
Google Cloud SDKのセットアップはどこまでWindowsユーザーを苦しめれば気が済むのか？

# モチベーション
- GoogleAppEngine/Goの`api_version:1`がdeprecateされる
- コードベースを`go1.6`から`go1.8`にしたい
- ローカルのSDKバージョンでは`api_version:1.8`を使えない
- つまり、あげざるをえない(;´Д｀)



```bash:アップデート前
>gcloud version
Google Cloud SDK 191.0.0
app-engine-go
app-engine-python 1.9.67
beta 2017.09.15
bq 2.0.29
core 2018.02.23
gcloud
gsutil 4.28
```


```bash:アップデート後
Google Cloud SDK 213.0.0
app-engine-go
app-engine-python 1.9.74
beta 2018.07.16
bq 2.0.34
cloud-datastore-emulator 2.0.1
core 2018.08.17
gcloud
gsutil 4.33
```
「**`gcloud components update`** コマンドでアップデートOKだぜb」的なメッセージを信じてEnterしたけれど、後述のエラーダンプを食らって消沈しました..。

# SDK のinstallでつまる

## 環境
- Windows 10 Pro, 64bit Version 1803 ビルド 17134


## 発生した問題

```console:UnicodeDecodeErrorってPythonのエラーなんですね。ぼくがやりたいのはSDKのインストールであってPythonのデバッグではないんですね
UnicodeDecodeError: 'ascii' codec can't decode byte ....
```

サクッとネットで解決策がのっていて、 **エンコーディングを`utf-8`にすればOK** とのことらしい。先達の叡智！ひゃっほ～！

```console:
UnicodeDecodeError: 'utf8' codec can't decode byte ....
```

ほほう・・・？

## SDKインストール手順
※前準備 - PCにインストールされていたPython2.7をアンインストールしました

- SDKのセットアップを実行しbundledpythonをインストールする
    - セットアップは失敗します
- PowerShellを使って、bundledpythonを使用させるための環境変数を設定する
- システム環境変数のGUIから追加したほうが確実

```
CLOUDSDK_PYTHON="E:\gcloud\google-cloud-sdk\platform\bundledpython\python.exe"
// E:\gcloud\はセットアップ時に指定したフォルダーです
```

### 【重要】Pythonの初期エンコーディングを`ascii`から`shift-jis`に変更する
- 理屈は未だ謎（重要）
- `sitecustomize.py`を作成し、`site-packagesフォルダー`に配置
    - 筆者の環境では `E:\gcloud\google-cloud-sdk\platform\bundledpython\Lib\site-packages` でした
- 参考：
    - [Python スクリプト実行時に UnicodeDecodeError が出る場合の対処方法 - Over&amp;Out その後](http://d.hatena.ne.jp/shu223/20111201/1328334689)
    - [【Python】site-packagesのパスを確認する方法【pip install】 - Qiita](https://qiita.com/chatrate/items/eb4b05cd1a6652529fd9)

```python:sitecustomize.py
import sys
sys.setdefaultencoding('shift-jis')
```
### インストールを実行
- `E:\gcloud\google-cloud-sdk\install.bat` をシェルから実行すると、エラーなく進み、プロンプトの問い合わせを`[Y]`します。
- gcloud CLI 実行時にもエンコーディング設定を反映させるため、環境変数を指定
```
CLOUDSDK_PYTHON_SITEPACKAGES="E:\gcloud\google-cloud-sdk\platform\bundledpython\Lib\site-packages"
```

### 補足）gcloud CLIで使用される環境変数

```shell:gcloud.cmdより
# "E:\gcloud\google-cloud-sdk\bin\gcloud.cmd"
rem <cloud-sdk-cmd-preamble>
rem
rem  CLOUDSDK_ROOT_DIR            (a)  installation root dir
rem  CLOUDSDK_PYTHON              (u)  python interpreter path
rem  CLOUDSDK_PYTHON_ARGS         (u)  python interpreter arguments
rem  CLOUDSDK_PYTHON_SITEPACKAGES (u)  use python site packages
```
# 完了！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/2883/7d1032cf-4f93-0223-bdea-4b1a2cd9a8bd.png)

# 勘所まとめ
1. SDKセットアップをそのまま実行すると Pythonの`UnicodeDecodeError` が出る
2. SDKバンドルのPython2.7を正しく使わせるため、以下が必要
    1. `site-packages`に初期エンコーディングを`shift-jis`に設定するスクリプトを配置する
    2. `CLOUDSDK_PYTHON` でPythonの実行パスを指定する
    3. `CLOUDSDK_PYTHON_SITEPACKAGES`で`site-packages`のパスを指定する
3. もう一度セットアップする
4. CLIにパスを通す（`E:\gcloud\google-cloud-sdk\bin`）


以上の手順により、GoogleCloudSDKのアップデートが無事に完了しました！ε-(´∀｀*)ﾎｯ

で、なにをするのが目的だったのか。。。。
Rails5.2　日本語化

調べてみるとconfig/application.rbの記述
`# config.i18n.default_locale = :de`
`config.i18n.default_locale = :jq`
に変更するとあるが上記の記述がない

設定がなくなっているみたいでconfig/initializersに置けとのこと

①config/initializers/i18n.rbを作成
`Rails.application.config.i18n.default_locale = :ja`


②辞書ファイルをconfig/locales/に置く

③再起動

参考サイト
https://qiita.com/yutackall/items/0ff97132f31e5bacbf00
http://docs.komagata.org/5355