「JavaScript」 カテゴリーの記事です。
iTunes Connect icon

[Electron][MacOS]Your application still accesses the following location(s):でリジェクト


追記:2017/06/18に大幅修正を加えました。

Electronで絶賛、開発中の「OutlineText」ですが、バージョンアップ版を審査に提出したところ、タイトルのようなメッセージとともにリジェクトが。

正確には、

2. 4 Performance: Hardware Compatibility (macOS)
Guideline 2.4.5(i) – Performance

Your application still accesses the following location(s):

‘/Applications/OutlineText.app/Contents/Resources/app/locales/en.json.tmp’

The majority of developers encountering this issue are opening files in Read/Write mode instead of Read-Only mode, in which case it should be changed to Read-Only.

これを初めてもらったとき、「そうか、たしかに自分で自分のappにアクセスしてしまったっらダメだな」と思って、OutlineText.app内のディレクトリにはロックをかけるような仕組みを作り直して、審査に再提出。

ところが、またリジェクト。理由は、判で押したように上記のメッセージで返ってきました。いろいろ試行錯誤した結果、4回連続でリジェクトを頂戴するという羽目に(審査チームももう少しヒントをくれても良いのに・・・)。

そこまでやって、ふと思い当たったのは、ひょっとすると、Entitlementsの指定が誤っているのではないか?ということで、先の記事中では、Electron でビルドするときは、シェルスクリプトでやっていて、以下のように設定しておりました。

Electornは、単体アプリではなくヘルパーアプリも一緒に動くので、codesignは本体同様にすべてに行ってあげないといけません。でないと、審査以前にアプリをアップロードするときに、アップローダーに怒られます。

この辺りは、「Electron アプリを Mac App Store に登録する手順」が参考になるでしょう。

ここで、問題になっていたのは、parent.plist 9行目のEntitlementsに、com.apple.security.files.user-selected.read-write が指定されていること。

このせいでいくらい対策を講じても、アクセスは可能になっていたというわけかと納得。そこで、以下のようにcom.apple.security.files.user-selected.read-onlyだけの記述にして審査へ再提出したら、ようやく審査に通りました。

ところが、いったんは審査を通ったものの、今度は保存ダイアログボックスが出ないというバグが発生・・・(これは審査チームも見逃したようです)。

考えてもみれば、そりゃそうですよね。read-onlyなのですから、保存ダイアログが出ないのは当たり前です。

で、結局は以下のように、指定を元に戻して再提出しました。具体的には、Entitlementsの指定で、read-onlyを、read-writeに書き換えています。

これでまた一から振り出しに戻り、先のテンプレ文とリジェクトをいただくことに。。。

そこで業を煮やした僕は、審査チームに「アピール」を送信してみることにしました。

Writes in the location are restricted and be open for read-only already. Please tell me the detailed occurrence procedure.

画像も添付しました。

read-only

ちゃんと「読み取り専用」として開いているぞ、と。

すると、二日後に以下のようなメッセージが届きました。

Hello,

Thank you for your inquiry. To clarify, the app is opening files in Read/Write mode instead of Read-Only mode, in which case it should be changed to Read-Only.
The file being accessed is:
‘/Applications/OutlineText.app/Contents/Resources/app/locales/en.json.tmp’

これを読んで、ふと、思い当たる節がありました。ひょっとして、ファイルの読み書きのところで、意図せずread-writeで読み込んでいる箇所があるのではないか?と。

実際、ありました。

保存するとき(ファイルに書き込むとき)、前に保存したディレクトリが存在しているかどうかチェックをして、なければデフォルトは「書類」フォルダを指定するというコードにしていました。参考にしたのは、「Check synchronously if file/directory exists in Node.js – Stack Overflow」です。

ひょっとすると、fs.lstatSyncが、read-writeでアクセスしに行っているのではないか?と思い(Node.jsの公式ページでは確認できなかったのですが)、Stack Overflowのページをもう一度確認してみると、回答が大幅に書き換えられていて、以下が推奨となっていました。

そこで、この部分を上記で書き直して、再度Appleに提出。程なくして、「Ready for sale」の返答があり、ようやくバージョンアップ版がApp Storeに並ぶことになりました。

やれやれ・・・一件落着です。

ちなみに、Appleの審査チームのアピールですが、質問形式で送ると、即座にテンプレで「サポートか、フォーラムに投げてね」的な回答が返ってきますが、「再現の手順」を教えてくれ、といった具体的な質問に対しては、ヒントになるくらいの回答が得られました。アピールの仕方にも、少し工夫が必要ですね。

 

Electron-icon

Electronでメニューへ動的にチェックを入れる


ElectronでMacOSアプリ作っています。

当サイトで「Open source & Free software」などと、標榜しておきながら、MacOSの方で有料アプリとして作って公開しています。(→気になる方はコチラからどうぞ)。

言い訳がましいですが、Appleのディベロッパーアカウントは1万円/年ほどかかっており、フリーで公開中のWindowsアプリのコードサイニング証明書更新など6万円/年と、すでに出銭の方が多いのではないかという状況でして。どうか忖度、願います。

そんなことはさておき、表題の件。

意外とサンプルが見つからなかったんですよね。

アプリ起動時のメニュー生成は、サンプルもいくつかみつかり、比較的簡単です。

JSON形式でテンプレートを作っておいて、それをアプリケーションメニューとしてセットするだけです。

ただ、これですと、セットした後にメニュー内容を変更するにはどうすれば良いのしょうか? たとえば、以下のような場合です。

sample-menu

チェックボックスの変更です。たとえば、上記の例でいえば、エンコーディングの種類の変更を行いたい(その選択したメニューにチェックを入れ直したい)場合です。

これはもう構築したメニュー全体から、変更したい該当のメニューを探し出すしかありません。そこで、前述のソースコードの7行目に注目してほしいのですが、メニューアイテムの属性値に「id」を追加しています。これを頼りに検索する関数をつくります。

これにより、変数encodingMenuには、「エンコーディング」以下のサブメニューオブジェクトが入ります。

これも関数にまとめてしまいましょう。

ここで注意したいのが、6行目のループで使われているsubmenu.itemsです。ここ、submenuだけにしがちなので、ご注意ください。

まとめるとこうなります。

本来ならよくあるように、’id’だけでズバッと該当のメニューを指定して変更できるのがベターなのですが、現状ではその方法がないので、メニュー内を探索して特定するしかなさそうですね。

 

JavaScriptでiOSアプリ、Androidアプリを作る環境は今はだいぶ整っている


しばらくJavaScriptでの仕事が続いていたので、じゃあ鉄は熱いうちに打つかと、作りたかったスマホゲームアプリをプライベートで、しかもJavaScript開発で一気呵成に作ってしまおうと思い立ちました。

そのゲームは以下に。もしお気に召していただけたのなら、お布施代わりに課金していただけるとうれしいです(フルバージョンになるだけの一回課金です)。

tamasabo

過去にも何度かJavaScriptでアプリ開発をやろうとして失敗したんですよね。

JavaScript開発でネイティブアプリにするフレームワークは、PhoneGapを初めとして、当時いくつか選択肢はありましたが、そのときは、どれもイマイチでした(できることが少なく、難度が高いという意味で)。

しかし、今回もCordva(PhoneGap)を使いましたが、当時とは状況がガラリと大きく変わっていたようです。

JavaScriptだけですべてを表現できるわけではない

「JavaScriptさえ書ければ、何でも表現できる!」と鼻息荒く始めるのですが、実際ハードウェアや、ネイティブ部分の壁にぶち当たると、もはやほとんど無力です。

今回でいえば、

  • アプリ内課金
  • アプリ内広告
  • ソーシャルシェア

です。中でもアプリ内課金では、iOS内のStoreKit(ネイティブ)を操作してiTunesサーバまで問い合わせるなんて、想像しただけでも、JavaScriptだけでは100%不可能。

「ああ、、、やっぱりムリだよなあ」と思って調べてたら、現在ではCordovaのプラグインが山ほどあって、アプリ内課金だけでも二つ三つ見つかる状況です。以下、今回のゲームアプリで使ったプラグインです。

アプリ課金
https://github.com/AlexDisler/cordova-plugin-inapppurchase

アプリ内広告
https://apps.admob.com
プラグイン
https://github.com/appfeel/admob-google-cordova

ソーシャルシェア
https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin

いずれもMITライセンスという素晴らしさ(たしかにGPLだとApple審査で弾かれますもんね。当たり前と言えば当たり前なのですが)。

PhpStormの万能感

phpstorm

まさか、JavaScriptによるスマホアプリ開発で、PhpStormが使えるとは思ってもみませんでした。

「PHPですよね?・・・」と知人から指摘を受けたとき、
「な、何を言ってるのか、わからねーと思うが・・・」

と、脳内ポルナレフ状態でした。たしかにPHP含めたサーバサイド開発環境じゃないのかよ、と思われますが、JavaScriptも扱うので、つまりは、iOS, Androidの統合開発環境としても使えます。

設定はとっても簡単。Cordovaのプロジェクトを作ったら、上部メニューにある「Select Run/Debug Configuration」を開きます。

select-run-and-debug

あとは、左ペインにある「PhoneGap/Cordova」を選択するだけです。

select-cordova

iOSの場合

ios-emulate

PhpStorm上で「実行」をすると、iOSの場合は、エミュレータが起動します。

別のプラグインを使えば、実機転送まで行けるそうですが、これだけでも充分すぎるくらいのデバッグ環境です。

Androidの場合

android-run

Androidの場合は、adbサーバが起動した状態で、Android端末がUSB接続されていれば、自動的に表示され、選択状態となります。

これでPhpStorm上の「実行」で、アプリはAndroid端末に転送され、デバッグできる状態になります。

一人でやっている人はすごい

以前はチームとして開発していたことがあるのですが、こうしてすべての工程を一人でこなすことになるとは思いも寄りませんでした。

今回は音関係以外、グラフィックやプログラミングは一人でやりましたが、なんと言っても大変だったのは、課金部分のデバッグでしょうか。一回だけでも課金が成功してしまえば、そのAppleアカウントはもうテストで使えなくなるからです。果たしていくつのAppleIDを作ったのやら・・・

あとは、それだけじゃないんですね。

リリースまで行くには、いろいろやるべきことがある。

プライバシーポリシーの作成(英語版も出す場合は、英語版も!)と、それを外部に置くための場所、ランディングページ(https://tamasabo.jp/)の作成をしなくてはならない。

App Storeに置くスクリーンショット画像の作成。解像度がiPhone、iPad含めて大量にあるので、地味に用意するのがたいへんだったり。

Appleの審査でのやり取りは依然として英語ですし、時差の関係か夜中の1時頃に、質問が飛んできたりします。

たいしたアプリではないので、さほど多くもないでしょうが、今後は開発者アカウントが存続するかぎり、サポートも続けていかないと、いけないのだろうなあ、と思っているところです。

JavaScriptでCryptoJSを使って、AESの暗号化と復号を行う


ウェブサイトを見回してみても、正しく実装されていなかったり、良いサンプルが無かったので、記事にしてみました。

→ DEMO&ソースコード:https://jsfiddle.net/hibara/qzono8jb/

CryptJSについては、以下にあります。
https://code.google.com/archive/p/crypto-js/

暗号化するにあたって

CryptJSの本題に入る前に、少し暗号化についてのお作法を知っておく必要があります。詳細は僕が書いた、別記事の「Visual Studio C#でファイルを暗号化してみる」を参照していただきたいですが、一応ざっとおさらい。

暗号化モードではCBCモードを使うのがベター

ブロック暗号方式と呼ばれるものは、その名のとおり、何バイトかずつブロック単位で暗号化していきますが、ここでやりがちなのがECBモードでしょうか。

ECBモード

これの何が問題かといえば、毎回同じデータ、同じパスワードだと、毎回同じ内容の暗号化データがでてきしまうという点です。

あるいは、各ブロックが小さくなるので、暗号化データへの総当たり攻撃(ブルート・フォースアタック)がしやすくなります。

基本的には、CBCモードを使いましょう。

CBCモード/暗号化

冒頭に、乱数による初期化ベクトル(Initialization Vector)を与えて、各暗号化ブロックに捻り合わせて行くイメージでしょうか。

CBCモード/復号する

ちなみに、暗号の大家であるブルース・シュナイアー氏がその著書『暗号技術大全』(日本語訳版は絶版・・・)の中でも、

ファイルを暗号化するのであれば、CBCモードがベストだろう。このモードを使えば、セキュリティは大きく向上するし、保存したデータに多少エラーが発生しても、同期エラーが発生することはまずない。アプリケーションが(ハードウェアではなく)ソフトウェアベースであれば、CBCがほぼ確実にいちばんいい。

と書いています。

パディングモード

ブロック暗号方式では、何バイトかのブロック単位で暗号化することにより、場合によっては、「端数」が出てしまいます。

これは暗号化されると、どこまでが暗号化データだったのか、復号時に正しく判別ができなくなくなるということです。

パディングモードでよく使われるのは、PKCS7のパディングモードでしょうか。

たとえば、以下の例ですと、データ長が8バイトで、実際のデータ列が9バイトあれば、残りの7バイトは、以下のように埋められます。

PKCS7パディングモード

つまり「余り」に埋められた合計サイズが、数値として埋められるというわけです。
これにより、復号時に、データ境界線をプログラムで判別できるようになります。

CryptoJSにはすべて揃っている

ところが、いざ、CBCモードで、PKCS7のパディングモードで暗号化したいと、該当のソースファイルを当たったら、どこにも見当たらない。「おかしい」と思って、本家のページを当たってみたところ、いずれも「Default」であるということが判明。

ユーザーが万一、なにも設定せずに使ってしまっても、黙ってCBCモードでPKCS7パディングモードで暗号化されるという親切設計でした(笑)。

CryptoJS supports the following modes:

CBC (the default)
CFB
CTR
OFB
ECB
And CryptoJS supports the following padding schemes:

Pkcs7 (the default)
Iso97971
AnsiX923
Iso10126
ZeroPadding
NoPadding

暗号化キーは鍵空間を広く使う

これは暗号化ユーティリティを使うすべてのユーザーにも言えることですが、パスワードはなるべく長い文字列で使ってほしいところです。当然、総当たり攻撃がしやすいという問題があるからです。

とはいえ、ユーザビリティを強制するのも、ツールの自由度を下げます。ただ、開発者側もそういった問題に少なからずフォローすることはできます。

たとえば、一文字のみパスワードを入れられても、鍵空間を目一杯使って、毎回異なるパスワードキーを生成してあげれば、多少この問題を和らげることができます(ただし、ブルートフォースアタックのような攻撃には何の訳にも立ちません)。

鍵空間

本題の「CryptoJS」

さて、本題の「CryptoJS」ですが、Google Code Archiveに上がっている、ライブラリです。そのサイトには、こう書かれています。

CryptoJS is a growing collection of standard and secure cryptographic algorithms implemented in JavaScript using best practices and patterns. They are fast, and they have a consistent and simple interface.

CryptoJSは、ベストプラクティス、ベストな形で、JavaScriptにおいての安全な暗号アルゴリズム標準となるべく開発しているものの一つです。これらは高速であり、一貫性とシンプルなインターフェイスを提供しています。

実際、オープンソースで、CDNやGitHubにも上がっています。

使い方は、たしかに簡単で、実際に使いたいjsファイルをhtmlヘッダ内で定義するだけです。

CryptoJSのAESを使ってみる

通常なら、「aes.js」だけで行けますが、今回は鍵空間を広げるためのライブラリを使うので、「pbkdf2.js」を含めました。

CryptoJS を使う上での注意点は、やはり「バイナリ」の扱いでしょうか。

おそらくウェブ上(サーバ間)でのデータのやりとりも考慮されているのか、データをバイナリデータ(Hex = 16進文字列)や、Base64エンコーディングして渡す場面が何度かあります。

ただ、CryptoJS では、それらを適宜、必要なデータへコンバートするためのメソッドも用意されています。

CryptoJS.enc.Hex.parse()
CryptoJS.enc.Base64.parse()
CryptoJS.enc.Utf8.parse()

などを駆使して暗号化します。

まずは、暗号化から。この程度のソースコードにjQueryを使っているのはご容赦ください。

暗号化の際の注意点としては、暗号に必要なsaltやIVなどを、暗号化データに含めないといけない点です。

ここでは単に、カンマ区切りとしていますが、他に方法があるのなら、どのような手段でも良いでしょう。

そして、復号はこちら。

以上です。

実際のデモは、先にも書きましたが、
https://jsfiddle.net/hibara/qzono8jb/

で、見られます。

QtでMacOSXアプリケーションをつくる


最近また、Qt を始めています。

実は、NokiaがQtを手放してから、もう終わったか・・・と、しばらく触っていなかったのですが、
しばらく見ないうちに、高機能で、マルチプラットフォーム化が進んでいたので、びっくりです。
商用ですが、Android、iOSにも対応しているようです。

そんなわけで、改めてなぜいま Qt なのかというと、Mac OSX アプリケーションが作りたくて。
心地よく日本語テキストを打ち込める、軽量な執筆エディターがほしくて探し回りましたが、
ぴったりのものが見つからないんですよね。

海外製のは、変換候補があさっての方へ飛んでいってしまったり、
段落下げしたら、以降、全部段落が下がるという、完全に海外文書仕様になっていて、
日本語的な一字下げのみということができなかったり、そもそも日本語対応は微妙なのが多い。

で、とりあえず僕はいま、Qtに、面倒なMacOSX側の処理をやってもらって、
あとは、エディタ部分も含め、WebView(Weblit+JavaScript)の方で
表示・編集できるように開発してこうと考えています。

いわゆる The QtWebKit Bridge(http://qt-project.org/doc/qt-5/qtwebkit-bridge.html)を使います。

Qt Creatorから、「新しいプロジェクト」を開くと、
「HTML5アプリケーション」という項目があるので、基本はそれで作ります。

ただ、これだと、シングルウィンドウのWebブラウザアプリと変わりがなくなってしまいます。
ファイルを保存したり、ファイルを開く、アプリ自体の設定なんかも各々のマシンに記憶しておきたい。

そうなると、MacOSXのネイティブなところをいじる必要があるわけです。
つまり、Qt(MacOSX)ネイティブ+JavaScriptのハイブリッドアプリケーションの構成で、というわけです。

ちなみに、エディタ部分は、CodeMirrorを使います。

これがなかなかの高機能で、ライセンスも、MITライセンス。
これをWebKitに組み込んで使っている海外製のエディタアプリケーションも多い。

このサンプルソースは、なかなか見当たらないのですが、以下の記事が参考になりました。

hybrid web+native: desktop codemirror
http://ariya.ofilabs.com/2011/09/hybrid-webnative-desktop-codemirror.html

「CodeMirrorを使う」という目的だけの、エディタの機能としては少なめのサンプルです。
とはいえ、限定されている分、ソースはシンプルで分かりやすいかもしれません。

ソースコードは、同ページにリンクが貼ってありますが、わかりにくいので、ここに再掲。
https://github.com/ariya/X2/tree/master/webkit/codemirror

ゆくゆくは、App Storeに出したいなあ、とは思っていますが、年間登録料をケチって野良配布するかもしれません。

とりあえず自分が使いたいツールを作るのが目標です。オープンソースも視野に入れています。
 
 

s