videos/insert(upload)

今度は、動画のアップロードをする場合。

Videos: insert  |  YouTube Data API (v3)  |  Google Developers

前回のプログラムで、成功した場合、UPLOAD_IDがレスポンスで返ってきたとおもう。
これを動画本体のアップロードで使う。

main.cppで、

ファイルサイズも取得するけど、ファイル自体は開いたままで、

UPLOAD_IDとACCESS_TOKENでリクエスト作成。

ファイルから読み込んだバイト列をそのままSSLソケット側に書き込む。

WSAStartup success!
soc = 532
connect success!
ctx = 00262c38
ssl = 0027c808
SSL_set_fd success!
SSL_connect success!
SSL_write written = 430
HTTP/1.0 200 OK
X-GUploader-UploadID: xxx
ETag: "m2yskBQFythfE4irbTIeOgYYfBU/rtjWaqrIEi2nVbogja7NHmlLzCI"
Vary: Origin
Vary: X-Origin
X-Goog-Correlation-Id: lc1OynhT080
Content-Type: application/json; charset=UTF-8
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Date: Mon, 11 Sep 2017 07:16:12 GMT
Content-Length: 865
Server: UploadServer
Alt-Svc: quic=":443"; ma=2592000; v="39,38,37,35"

{
 "kind": "youtube#video",
 "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/rtjWaqrIEi2nVbogja7NHmlLzCI\"",
 "id": "lc1OynhT080",
 "snippet": {
  "publishedAt": "2017-09-11T07:12:01.000Z",
  "channelId": "UCYE61NR1q3chykYt1BY2m_w",
  "title": "test.mp4",
  "description": "videos/insert",
  "thumbnails": {
   "default": {
    "url": "https://i.ytimg.com/vi/lc1OynhT080/default.jpg",
    "width": 120,
    "height": 90
   },
   "medium": {
    "url": "https://i.ytimg.com/vi/lc1OynhT080/mqdefault.jpg",
    "width": 320,
    "height": 180
   },
   "high": {
    "url": "https://i.ytimg.com/vi/lc1OynhT080/hqdefault.jpg",
    "width": 480,
    "height": 360
   }
  },
  "channelTitle": "st bg",
  "tags": [
   "test",
   "video"
  ],
  "categoryId": "22",
  "liveBroadcastContent": "none",
  "localized": {
   "title": "test.mp4",
   "description": "videos/insert"
  }
 }
}

続行するには何かキーを押してください . . .

成功すると、こんなレスポンス。
サーバ側も、

アップロード中
アップロード中

ここから、

アップロード完了
アップロード完了

こうなって、

成功
成功

情報もちゃんと付加されてる。
このようにアップロードできる。

Sample/youtube/videos/insert_upload/src/videos at master · bg1bgst333/Sample · GitHub

videos/insert

YouTubeに動画をアップロードするには、videos/insertを使う。

Videos: insert  |  YouTube Data API (v3)  |  Google Developers

POSTで"/youtube/v3/videos"である。
それと、このAPIjsonを送るのと動画本体を送る2段階がある。
今回はjsonを送る場合。

main.cppで、

動画ファイルのサイズを計算。

json作成。
UPLOAD_FILENAMEは動画ファイル名。

で、あとはリクエスト作成。
ここでACCESS_TOKENを使う。
最後に先ほどのjsonを連結してる。
で、ここではファイルは書き込まない。jsonを送るだけである。

WSAStartup success!
soc = 536
connect success!
ctx = 011b0800
ssl = 011cf6a0
SSL_set_fd success!
SSL_connect success!
SSL_write written = 550
HTTP/1.0 200 OK
X-GUploader-UploadID: xxx
Location: https://www.googleapis.com/upload/youtube/v3/videos?part=snippet&uploadType=resumable&upload_id=xxx
ETag: "m2yskBQFythfE4irbTIeOgYYfBU/rtjWaqrIEi2nVbogja7NHmlLzCI"
Vary: Origin
Vary: X-Origin
X-Goog-Correlation-Id: lc1OynhT080
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Date: Mon, 11 Sep 2017 07:12:01 GMT
Content-Length: 0
Server: UploadServer
Content-Type: text/html; charset=UTF-8
Alt-Svc: quic=":443"; ma=2592000; v="39,38,37,35"


続行するには何かキーを押してください . . .

X-GUploader-UploadIDの後にあるxxxとか、upload_idのxxxとか、このxxxはUPLOAD_IDなのでこれは後で使うので覚えておこう。
一瞬だけ、

いけるか?
いけるか?

こういうのが出てきたときがあったけど、

ダメでした
ダメでした

当然、jsonだけなので動画はなし。

Sample/youtube/videos/insert/src/videos at master · bg1bgst333/Sample · GitHub

oauth2/token

認証コードが取得出来たら、今度はトークンを取得する。

Using OAuth 2.0 to Access Google APIs  |  Google Identity Platform  |  Google Developers

main.cppで、

前回、最後に取得した認証コードを入力。

CLIENT_ID、CLIENT_SECRET、REDIRECT_URI、どれもここまでに出てきた要素なのでそれを当てはめる。

code: xxx
WSAStartup success!
soc = 524
connect success!
ctx = 011c3238
ssl = 011de8e8
SSL_set_fd success!
SSL_connect success!
SSL_write written = 372
HTTP/1.0 200 OK
Content-Type: application/json; charset=utf-8
X-Content-Type-Options: nosniff
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: Mon, 01 Jan 1990 00:00:00 GMT
Date: Thu, 07 Sep 2017 08:09:39 GMT
Content-Disposition: attachment; filename="json.txt"; filename*=UTF-8''json.txt
Server: ESF
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Alt-Svc: quic=":443"; ma=2592000; v="39,38,37,35"
Accept-Ranges: none
Vary: Accept-Encoding

{
  "access_token" : "xxxxx",
  "expires_in" : 3600,
  "refresh_token" : "xxxxxxx",
  "token_type" : "Bearer"
}
続行するには何かキーを押してください . . .

こんな感じでトークンが取得できる。

Sample/google/oauth2/token/src/oauth2 at master · bg1bgst333/Sample · GitHub

oauth2/auth

YouTubeで動画をアップロードしたりする時、まずはGoogleのOAuth2認証を通過しないといけない。

Using OAuth 2.0 to Access Google APIs  |  Google Identity Platform  |  Google Developers

認証情報
認証情報

認証情報からウィザード選択。

その他のUI
その他のUI

Windowsなのでその他のUI。

クライアントID作成
クライアントID作成

クライアントIDを作成。

IDが作成された
IDが作成された

ダウンロードボタンでjsonファイルをダウンロードして、完了。

client_id.jsonの内容は、

{"installed":{"client_id":"xxx.apps.googleusercontent.com","project_id":"bg1youtubetest1-xxxxxx","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://accounts.google.com/o/oauth2/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"xxx","redirect_uris":["xxx","http://localhost"]}}

ちょっと改変したけど大雑把にこんな感じのファイルがダウンロードされる。

main.cppで、

と書くのだが、

Google API OAuth2.0のトークン取得手順 - Qiita
Google API OAuth2.0のアクセストークン&リフレッシュトークン取得手順メモ - Qiita

CLIENT_IDは、client_id.jsonにあるやつ。
REDIRECT_URIは、redirect_urisの1番目のやつ。(localhostじゃなくてその前。)
SCOPEは、
Choose Auth Scopes  |  Gmail API  |  Google Developers
ここにサービスごとに書いてあるらしい。ただ、YouTubeはないな。
いろいろ調べたら、YouTubeは、
https://www.googleapis.com/auth/youtube
らしい。

で実行すると、

WSAStartup success!
soc = 520
connect success!
ctx = 00c95690
ssl = 00caed88
SSL_set_fd success!
SSL_connect success!
SSL_write written = 324
HTTP/1.0 302 Found
Content-Type: application/binary
Location: xxx
P3P: CP="This is not a P3P policy! See https://support.google.com/accounts/answer/151657?hl=en for more info."
Content-Language: en-US
Date: Thu, 07 Sep 2017 03:50:44 GMT
Server: ESF
Content-Length: 0
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Set-Cookie: NID=111=xcq3PaRj5M4OBMdXAkmBuD_jO_uKYdfHe2vQwihJa8RQx4SwaU1J3SGQy9xfhNfLw1TRcpcqlPQAqv8UgOhwp4P5DfLevVrbumrIBw26Uqrp__hosTl4a1T0_Y4GdehB;Domain=.google.com;Path=/;Expires=Fri, 09-Mar-2018 03:50:44 GMT;HttpOnly
Alt-Svc: quic=":443"; ma=2592000; v="39,38,37,35"


続行するには何かキーを押してください . . .

本来、このリクエストをブラウザでやると、上のLocation: xxxによって、そこにリダイレクトされる。
"xxx"の部分に、とても長いURLが入ってるので、そこに行くと、Googleの認証ボタンページに飛び、それを押すと、エディットボックスに認証コードが入っている。
で、この認証コードとそれまでに得た情報でトークンが得られるのだが、今回はあくまで認証コード取得までとする。

Sample/google/oauth2/auth/src/oauth2 at master · bg1bgst333/Sample · GitHub

videos/list

YouTube Data API (v3)でYouTubeに動画をアップロードしたり、情報を追加したり、取得したりする。
まずは、videos/listで動画リストを取得する。

Videos: list  |  YouTube Data API (v3)  |  Google Developers

まずは、

Google APIs
Google APIs

この中で、左下のYouTube APIYouTube Data APIへ行く。

規約更新
規約更新

規約更新を了承して、

YouTube Data API v3
YouTube Data API v3

ここに来る。
ダッシュボードで、

プロジェクト選択
プロジェクト選択

と言われるが、無いので、

新しいプロジェクトを作成
新しいプロジェクトを作成

作成。

まだこの状況
まだこの状況

でもまだこの状況なので、

有効にする
有効にする

有効にするをクリック。

有効にしています
有効にしています

この状態で待つと、

完了
完了

こうなるので、認証情報を作成。

作成
作成

で、とりあえず、

こうしてみる
こうしてみる

こうしてみる。これで作成すると、

APIキー
APIキー

APIキーが発行される。

できたけど
できたけど

OAuth同意画面も作成しておく。

OAuth同意画面
OAuth同意画面

これを保存して、

完了
完了

完了。

動画をアップロード
動画をアップロード

動画をアップロードする。

完了
完了

完了。

短縮リンク
短縮リンク

短縮リンク。

さて、あとはコンソールアプリで情報取得クライアントを作成する。
OpenSSLでGETで、

こんなリクエスト。
VIDEO_IDは"sk2~"で始まるやつかな。

WSAStartup success!
soc = 508
connect success!
ctx = 0047eca8
ssl = 004971e8
SSL_set_fd success!
SSL_connect success!
SSL_write written = 160
HTTP/1.0 200 OK
Expires: Wed, 06 Sep 2017 11:07:19 GMT
Date: Wed, 06 Sep 2017 11:07:19 GMT
Cache-Control: private, max-age=300, must-revalidate, no-transform
ETag: "m2yskBQFythfE4irbTIeOgYYfBU/o5SsdPeHUfLk6rTW15Hxc0OnbaA"
Vary: Origin
Vary: X-Origin
Content-Type: application/json; charset=UTF-8
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Content-Length: 1596
Server: GSE
Alt-Svc: quic=":443"; ma=2592000; v="39,38,37,35"

{
 "kind": "youtube#videoListResponse",
 "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/o5SsdPeHUfLk6rTW15Hxc0OnbaA\"",
 "pageInfo": {
  "totalResults": 1,
  "resultsPerPage": 1
 },
 "items": [
  {
   "kind": "youtube#video",
   "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/sL5Lew4kYnMFB5ggFNR0OiKt9mE\"",
   "id": "sk2cH2nkMQY",
   "snippet": {
    "publishedAt": "2017-09-06T02:40:44.000Z",
    "channelId": "UCYE61NR1q3chykYt1BY2m_w",
    "title": "VizCommand 2017 05 28 8 46 19",
    "description": "This Application is Ultimate Command Prompt Terminal.\nhttps://github.com/bg1bgst333/VizCommand",
    "thumbnails": {
     "default": {
      "url": "https://i.ytimg.com/vi/sk2cH2nkMQY/default.jpg",
      "width": 120,
      "height": 90
     },
     "medium": {
      "url": "https://i.ytimg.com/vi/sk2cH2nkMQY/mqdefault.jpg",
      "width": 320,
      "height": 180
     },
     "high": {
      "url": "https://i.ytimg.com/vi/sk2cH2nkMQY/hqdefault.jpg",
      "width": 480,
      "height": 360
     },
     "standard": {
      "url": "https://i.ytimg.com/vi/sk2cH2nkMQY/sddefault.jpg",
      "width": 640,
      "height": 480
     },
     "maxres": {
      "url": "https://i.ytimg.com/vi/sk2cH2nkMQY/maxresdefault.jpg",
      "width": 1280,
      "height": 720
     }
    },
    "channelTitle": "st bg",
    "tags": [
     "Windows"
    ],
    "categoryId": "22",
    "liveBroadcastContent": "none",
    "localized": {
     "title": "VizCommand 2017 05 28 8 46 19",
     "description": "This Application is Ultimate Command Prompt Terminal.\nhttps://github.com/bg1bgst333/VizCommand"
    }
   }
  }
 ]
}

続行するには何かキーを押してください . . .

成功するとこんな風に動画のリストを返す。

Sample/youtube/videos/list/src/videos at master · bg1bgst333/Sample · GitHub

print

PHPで文字列を出力するにはprintを使う。

PHP: print - Manual

関数ではなく、言語構造(仕様?)なので、括弧は無くていい。

まず、PHPのインストールから、

$ sudo yum install php
[sudo] <user> のパスワード:
Yum command has been deprecated, redirecting to '/usr/bin/dnf install php'.
See 'man dnf' and 'man yum2dnf' for more information.
To transfer transaction metadata from yum to DNF, run:
'dnf install python-dnf-plugins-extras-migrate && dnf-2 migrate'

依存性が解決されました。
================================================================================
 Package               アーキテクチャ
                                     バージョン            リポジトリ      容量
================================================================================
インストール:
 php                   x86_64        5.6.31-1.fc24         updates        2.7 M
 php-cli               x86_64        5.6.31-1.fc24         updates        4.1 M
 php-common            x86_64        5.6.31-1.fc24         updates        1.1 M
 php-pecl-jsonc        x86_64        1.3.10-1.fc24         updates         57 k

トランザクションの要約
================================================================================
インストール  4 パッケージ

総ダウンロード容量: 7.9 M
インストールされる容量: 30 M
これでいいですか? [y/N]: y
パッケージをダウンロードしています:
(1/4): php-common-5.6.31-1.fc24.x86_64.rpm      611 kB/s | 1.1 MB     00:01    
(2/4): php-5.6.31-1.fc24.x86_64.rpm             1.3 MB/s | 2.7 MB     00:01    
(3/4): php-cli-5.6.31-1.fc24.x86_64.rpm         1.6 MB/s | 4.1 MB     00:02    
(4/4): php-pecl-jsonc-1.3.10-1.fc24.x86_64.rpm   78 kB/s |  57 kB     00:00    
--------------------------------------------------------------------------------
合計                                            2.4 MB/s | 7.9 MB     00:03     
トランザクションの確認を実行中...
トランザクションの確認に成功しました。
トランザクションのテストを実行中...
トランザクションのテストに成功しました。
トランザクションを実行中...
  インストール  : php-pecl-jsonc-1.3.10-1.fc24.x86_64                       1/4 
  インストール  : php-common-5.6.31-1.fc24.x86_64                           2/4 
  インストール  : php-cli-5.6.31-1.fc24.x86_64                              3/4 
  インストール  : php-5.6.31-1.fc24.x86_64                                  4/4 
  検証中        : php-5.6.31-1.fc24.x86_64                                  1/4 
  検証中        : php-cli-5.6.31-1.fc24.x86_64                              2/4 
  検証中        : php-common-5.6.31-1.fc24.x86_64                           3/4 
  検証中        : php-pecl-jsonc-1.3.10-1.fc24.x86_64                       4/4 

インストール済み:
  php.x86_64 5.6.31-1.fc24             php-cli.x86_64 5.6.31-1.fc24            
  php-common.x86_64 5.6.31-1.fc24      php-pecl-jsonc.x86_64 1.3.10-1.fc24     

完了しました!
$

インストール終わったら、

$ sudo vi php.ini

[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = "Asia/Tokyo"

/etcでphp.iniの編集。

$ cd ~
$ sudo systemctl restart httpd
$

Apacheのリスタート。

$ cd /var/www/
$ ls -al
合計 16
drwxr-xr-x.  4 root root 4096 12月 23  2016 .
drwxr-xr-x. 22 root root 4096  9月  5 10:27 ..
drwxr-xr-x.  2 root root 4096 12月 23  2016 cgi-bin
drwxr-xr-x.  2 root root 4096 12月 23  2016 html
$ chmod 777 cgi-bin
chmod: 'cgi-bin' のパーミッションを変更しています: Operation not permitted
$ sudo chmod 777 cgi-bin
[sudo] <user> のパスワード:
$ sudo chmod 777 html
$ ls
cgi-bin  html
$ cd html/
$ ls
$ vi index.php
$

あまりよろしくないけど、とりあえずCGIPHPが動くように。
/var/www/htmlの中でindex.phpを作って、

<html>
  <head>
    <title>print</title>
  </head>
  <body>
    <?php
      print "Hello PHP";
    ?>
  </body>
</html>

こう書く。

index.phpをブラウザで実行
index.phpをブラウザで実行

こうなる。

print.phpに名前変えたけど内容は同じ。

Sample/php/print/print/src/print at master · bg1bgst333/Sample · GitHub

DDX_Radio

ラジオボタンの場合は、DDX_Radioマクロ。

DDX_Radio | Microsoft Docs

最初のアイテムはGroupをTrueに
最初のアイテムはGroupをTrueに

配置するときは、上から順に。
リソースIDの範囲でグループ化されるので。
最初のアイテムでは、GroupをTrueに。

2つ目以降はGroupをFALSEに
2つ目以降はGroupをFALSEに

2つ目以降はGroupをFALSEに。

最初のアイテムで変数を追加
最初のアイテムで変数を追加

最初のアイテムに戻って右クリックから変数の追加。

変数の種類はint
変数の種類はint

変数の種類はintになっている。
m_xvRadio1にアイテム3つのうちのどれが選択されているかどうかが、0から始まる整数で入っている。

確かにint。

DDX_Radioがある。

Button1が押されたら、m_xvRadio1の値を表示。

1つ目が選択されている
1つ目が選択されている

1つ目が選択されている場合、

m_xvRadio1は0
m_xvRadio1は0

m_xvRadio1は0。

2つ目
2つ目

2つ目の場合、

m_xvRadio1は1
m_xvRadio1は1

m_xvRadio1は1。

3つ目の場合
3つ目の場合

3つ目の場合、

m_xvRadio1は2
m_xvRadio1は2

m_xvRadio1は2。

Sample/mfc/DDX_Radio/DDX_Radio/src/DDX_Radio at master · bg1bgst333/Sample · GitHub