2011年12月17日土曜日

HomebrewでSpidermonkeyのデバッグビルドをインストール

デバッグモードでビルドしないとディスアセンブルする関数が使えないので、デバッグビルドしてインストールします。

デフォルトのFormulaはデバッグビルドがOFFになっているので、

➜  ~  brew edit spidermonkey

で、js/src/configureのところに(二箇所configureがあるけど下のやつ)

--enable-debug --disable-optimize

のオプションを追加します。 via SpiderMonkey Build Documentation - MDN

NewImage

これで、dis関数が使えるSpidermonkeyがビルドできるようになるので、

➜  ~  brew install spidermonkey

でインストール

JavaScriptの無名関数の実行 (function(){})() と (function(){}()) の違い | 圧縮電子精神音楽浮遊構造体を見て、やってみたかっただけです。

js> dis(function(){ new function(){} });
flags: LAMBDA NULL_CLOSURE
main:
00000:  trace
00001:  lambda (function () {})
00004:  null
00005:  new 0
00008:  pop
00009:  stop

Source notes:
  0:     5 [   5] pcbase   offset 4
js> dis(function(){ (function(){})() });
flags: LAMBDA NULL_CLOSURE
main:
00000:  trace
00001:  lambda (function () {})
00004:  null
00005:  call 0
00008:  trace
00009:  pop
00010:  stop

Source notes:
  0:     5 [   5] pcbase   offset 4
js> dis(function() { (function(){}()) });
flags: LAMBDA NULL_CLOSURE
main:
00000:  trace
00001:  lambda (function () {})
00004:  null
00005:  call 0
00008:  trace
00009:  pop
00010:  stop

Source notes:
  0:     5 [   5] pcbase   offset 4

2011年12月5日月曜日

Redmineにgitレポジトリを認識させる

Redmineから参照するgitレポジトリはbareというレポジトリにしないと認識しないらしい

コラム:公開リポジトリと通常のリポジトリとbareリポジトリ  Gitの公開リポジトリは通常、管理ファイルのみを持つ「bareリポジトリ」として作成される。通常bareリポジトリでは作業ツリーの変更やコミットといった操作は行わず、ファイルのやりとりにのみ使用する。また、慣例としてbareリポジトリとして使用するディレクトリには「.git」という拡張子が付けられる。  bareリポジトリは、「--bare」オプションを付けてでgit initを実行することで作成できる。

Gitを使いこなすための20のコマンド - SourceForge.JP Magazine : オープンソースの話題満載

サーバ上のgitレポジトリでbareレポジトリを作る必要があったりして面倒

$git init --bare
$git flow init #ローカルでgit flow導入してるならサーバへgit push --allでもOK
$git symbolic-ref HEAD refs/heads/develop

bareレポジトリはブランチを変えられないそうなので、git checkout developの代わりに、シンボリックリンク的に貼る必要がある。

普通のレポジトリを認識して欲しい。

2011年10月23日日曜日

JavaScript Gardenの日本語ページをビルド

JavaScript Garden日本語訳も書かれていて(まだ途中まで)Layzie/JavaScript-Garden - GitHubにソースコードが置かれている。

多言語の構成が元から用意されていて、Translating_ja - GitHubに書かれているようにnodeを使ってビルドする事で htmlとして見られるようにする。

git clone https://github.com/Layzie/JavaScript-Garden.git
cd JavaScript-Garden
npm install jade neko fomatto node-markdown
node build build.js
open site/ja/index.html

という感じで、nodeを使ってビルドすればhtmlができるので以下のように見られる。

NewImage

まあ、そのうち本家にpull requestされてメニューからたどれるようになると思うけど。

 

2011年10月16日日曜日

Doxygen + graphvizでObjective-Cのクラス図

Doxygen + graphviz(dot)を使うことでObjective-Cクラス間の関係をクラス図的に表示するドキュメントを作成できる。

brew install doxygen graphviz

でそれぞれインストールを行う。

doxygenでドキュメントを生成するときに設定ファイルDoxyfileにHAVE_DOTをYESにしてgraphvizのパスを設定するなどして、graphvizを使うようにする設定が必要になる。

こんな感じのDoxyfileにしてたみた。
この設定ファイルを使って、doxygen Doxyfile みたいな感じのコマンドを生成したソースファイルがあるディレクトリで実装するとhtmlフォルダができる。

実際にコードを読むのはAppCodeでやると思うので、もっとグラフィカルな感じでクラスのメソッド関係とかをグリグリ見られるのがあると面白そう。

 

2011年9月25日日曜日

quickrun.vimでblockdiagのプレビューする

blockdiagを書くとき、blockdiagに対応したエディタみたいなものは特に無いのでvimで書いていたのですが、やっぱりプレビューがとても面倒で、
➜ ~ blockdiag -a hoge.diag && open hoge.png という感じのコマンドを毎回実行していました。(MacなのでPreviewが勝手に立ち上がってくれる)

これをVimから一発でできるようにするため、Quickrun.vimの設定を書いて見ました。

let g:quickrun_config['diag'] = {
            \'command': '$HOME/.pythonbrew/pythons/Python-2.7.2/bin/blockdiag',
            \'exec': ['%c -a %s -o %{expand("%:r")}.png', 'open -g  %{expand("%:r")}.png'],
            \'outputter':'message',
            \}
" blockdiag
autocmd BufWinEnter,BufNewFile *.diag set filetype=diag

ちょっと汚いですが、こんな感じになりました。

pythonbrewを使ったPython環境にblockdiagを入れているので、そのままcommandにblockdiagと書くとcommand not foundになってしまったので直接パスを指定しています。
openコマンド(-gでバックグラウンドでプロセスが起動)を使っているので、Macでしか動かないと思います。(openの部分を環境ごとに変えればいいけど)
また、デフォルトだとdiagというタイプは存在してないので、自動的にファイルタイプを設定するようにしておく必要もあります。
outputterはよくわからなかったけど、とりあえずこうしてみた。

以下が書いてる様子。quickrunするたびにpreviewも更新できるので、そこそこ便利になった。

2011年9月21日水曜日

(括弧)とスペースを使わないでXSS

タイトルのように括弧とスペースを入力値に使えないような状態でXSSするものを見つけて結構面白かったのでメモ。
その時のサイトを再現したような感じのページ

JS Bin

クイズとか書いてありますが、興味ある方は下の解答を読む前にやってみるといいかもしれないですね。

自分が考えながらやった感じの解答は以下のようなものです

以下に実証コードを作成するまでの経緯を書いておくと

---

  1. 検索キーがエスケープされてない事に気づく
  2. 単純に<script>alert(1)</script>を検索キーとした場合()が大文字変換されてJavaScriptコードはエラーになる
  3. 検索キーにスペースが入ると検索結果が変わり、この場合はエスケープされて正しく出力される
  4. スペースと括弧を使わずにスクリプトを実行するという条件でも、window.nameを使い任意のスクリプトを実行させることが可能。
    XSS例題(下書き中) - st4rdustの日記
    2009-08-17 - hoshikuzu | star_dust の書斎
  5. XSS例題のようなaリンクのtargetにスクリプトを仕込んでやる方法でとりあえず実行できる事は確認したが、実際に罠として踏ませるテストケースにために自動的に実行できるようにする。
  6. window.openでtarget指定や、aリンクを用意してdocument.createEvent('MouseEvents')で自動的に踏ませる方法はポップアップブロックに阻まれてしまった。(許可すれば実行はできる)
    Chrome で画像の一括ダウンロード - Griever
  7. target指定があると、ポップアップブロックされてしまうが、targetはframeの指定にも利用できる。
    <a>-HTML5タグリファレンス
  8. つまり、以下のようにtargetに仕込んだスクリプトと同じ名前をつけたiframeを用意すれば、ポップアップせずに iframe内のURLが書き換わるようになり、そのURLにJavaScriptの実行コードを仕込むことができる。
<iframe src="http://攻撃対象サイト" name="javascript:alert(1)"></iframe>
<a id="xss" href="http://攻撃対象サイト/%3Cscript%3Elocation.href=window.name%3C/script%3E" target="javascript:alert(1)">
XSS
</a>
後は、マウスクリックを自動でさせるようにすれば、罠ページにアクセスしたら任意のJavaScriptを実行できる。

----

という感じの流れで、上記の解答例を作ってました。
window.nameで実行できることにはすぐ気づいたのですが、それを自動的に実行させる方法を色々試していたので何か遠回りな方法になっています。

window.nameの参考リンクにもでてきた@s_hskzさんによる解答はもっとシンプルで、こっちのほうが失敗もないし良いと思います。

他にも解答はあるような気がしますがこんなところで。

再現したページのしょっぱいPHPコードは http://codepad.viper-7.com/1EvHix で見られます。

iOSアプリのコンソールに出てくるアプリ名を変更する

iOSアプリを書いてる時に、Targetを複製したりするとアプリ名やコンソールに出てくる名前などデフォルトで"元Target名 copy"という感じになってしまいます。
identifierはすぐわかりますが、特にコンソールに出てくる名前の変え方がよくわかりませんでした。

InfoタブのBundle nameがそれに該当するようですが、Bundle nameは${PRODUCT_NAME}を参照しているため、${PRODUCT_NAME}を変更する方が合理的です。
${PRODUCT_NAME}はBuild SettingsタブのPackagingセクションにあります。
${PRODUCT_NAME}はConfigurationsごとに変更できるみたいです(まとめて変更もできる)

Ninshin  ninshin xcodeproj

${PRODUCT_NAME}が変更されると、ファイルとして出てくる.appのファイル名も変わるため、コンソールに出てくる名前も変更することが出来ました。

IOSシミュレータ

とてもわかりづらいですね。はい。

2011年9月17日土曜日

Macでblockdiag動かすためにPython環境作りなおした

homebrewでのPythonが壊れた感じで、brew install pythonとかもまともに出来なかったので、pybrewを使ってPythonをインストールするようにした。

が、その前にbrewで動いてたPythonのやつとかを全部消したくなったので、

osx - How to uninstall Python 2.7 on a Mac OS X 10.6.4? - Stack Overflow

を参考にアンインストール的なことを行った。

sudo rm -rf /Library/Frameworks/Python.framework/Versions/2.7
sudo rm -rf "/Applications/Python 2.7"
ls -l /usr/local/bin | grep '../Library/Frameworks/Python.framework/Versions/2.7' # これ見るとpythonへのリンクしてるものがわかるので、削除する

で、次にpybrewをインストールした。

$ curl -kL http://github.com/utahta/pythonbrew/raw/master/pythonbrew-install | bash

そして.zshenvにsource $HOME/.pythonbrew/etc/bashrcを書き込んだ。

こうすればpybrewコマンドが使えるようになるので、

pybrew install <version>

で好きなバージョンのPythonをインストールできる。
そのまま2.7.2をインストールしようとしたらエラーになったけど、-fオプションをつけたらインストールできた。

最終的に.zshrcは以下みたいな感じに

# pybrew
if [[ -s $HOME/.pythonbrew/etc/bashrc ]]; then
  source $HOME/.pythonbrew/etc/bashrc
  pybrew switch 2.7.2 >/dev/null
fi

次にblockdiagのインストール。

blockdiag の概要 — blockdiag v1.0 documentation

の手順どおりにやればいいので、freetype2をインストールして、
自分の場合はpipを使いたかったので、

$easy_install pip
$pip install pil
$pip install blockdiag

という感じでインストールできた。

ここまで来るのに一ヶ月かかるぐらいPythonへの苦手意識がつよくて、今まで一回で何かをインストールできた記憶が殆どない。

 

「8.8.8.8,8.8.4.4」より速い「129.250.35.250」より速いDNS

「個人によって効果が異なる可能性があります」という系統のお話なので、
そういう数値の見比べして設定したい方はDNS Jumperとかのソフトウェアを使えばいいんじゃないでしょうか。
DNSの速度比較と設定まで自動的に行えます。(Windows限定だけど)

DNSを変えよう的な話はDNSキャッシュポイズニングとかそういう時にあったのを思い出した。

そういえば、Google Public DNSはいつの間にか日本にもあったんですね。

今時のブラウザはDNS prefetchを持ってる(ChromeとFirefoxにあるのは覚えがある)のでリロードタイミングだとDNSの速度比較にならないという話でもあったけど。

2011年9月15日木曜日

アプリ内課金(In App Purchase)に関するリジェクト事例と仮想通貨について

Appleのアプリ審査ガイドライン、UIWebViewに関係するリジェクト事例と似たようなお話ですが、In App Purchaseについてのリジェクト理由や事例などを調べてみました。

最初に、アプリ内課金での仮想通貨購入について

初めにIn App Purchase プログラミングガイドを見てしまったのが混乱の元みたいな気がしますが、In App Purchase プログラミングガイドには以下のように書かれています。 (iOS Developer Library)

In App Purchaseは、プロダクトを作り出すための汎用のメカニズムを提供しますが、プロダクトの
実装方法の詳細はデベロッパにゆだねています。ただし、アプリケーションの設計においては、以
下に示すように留意すべき重要なガイドラインがいくつかあります。

●アプリケーションの中で提供できるのは電子商品または電子サービスに限られています。In App
Purchaseを使って実物の商品やサービスを販売することはできません。

●中間通貨のようなアイテムを提供することはできません。 これは、特定の商品やサービスを購
入するということがユーザに認識されることが重要であるためです。

●販売用に提供するアイテムには、ポルノ、誹謗、中傷、ギャンブル(ギャンブルのシミュレー
ションであれば問題ありません)や、それらに関連するようなものを含めないようにします。

という感じで、"中間通貨のようなアイテムを提供することはできません"と書かれています。
この中間通貨というものが、mixiアプリやモバゲーなどで見かけるような仮想通貨(ポイントを購入するようなもの)だと思っていたのですが、株式会社アドウェイズのアプリなどは、
In App Purchaseで仮想通貨(魂だったり、愛だったり)を購入することができるようになっていて、これはガイドラインとは違うのか?と思いました。

基本に振り返ってAppleのアプリ審査基準ガイドライン(Appleのアプリ審査ガイドラインに日本語訳のリンクまとめてある)を見ると、

11. Purchasing and currencies

11.4 Apps that use IAP to purchase credits or other currencies must consume those credits within the application

というように仮想通貨の購入に関する注意事項が書いてあったり、Appleの審査項目への質問が多いので私見を晒す - ku-sukeのはてなダイアリーの11を見るとわかりやすいですが、
仮想通貨の購入自体は容認されていて、その購入した仮想通貨がアプリ内で完結しなければならないということが書かれている。
つまり、 そのアプリで購入した仮想通貨が、他のアプリと連動したり、Web版から使えたりしたらマズイのかもしれない。(アプリ版があるのでWebからは使わせないとかでもいいと思うけど)

なので、アプリ内で購入した通貨はアプリの外から触れるようにしてはいけないことに注意すれば、仮想通貨自体は扱ってもよいもののようだ。(実際に確かめたわけではないので保証はできないが)

次にIn App Purchaseに関するリジェクト事例について

iPhone App in App Purchase リジェクトされました|Across the Star Cluster
Reject Database for iPhone:detail

「購入ボタン」を押す前にiTunes StoreのIDとPassを聞いてはいけない。

リジェクト事例共有:アプリ内課金 « ジェネシックスブログ

In App Purchaseで設定する課金の種類は用途に合わせて正確に設定しないといけない。

In App Purchaseのデバックが出来ません。 - iPhone-dev.jp掲示板 | Google グループ

In App Purchase時にiTunes アカウントの使用する旨メッセージ表示する必要がある。

独自課金を使ったリジェクト事例について - iPhone-dev.jp掲示板 | Google グループ

最近は似たようなアプリを大量リリースすると厳しめの判定を受けるので、In App Purchaseを使ってまとめるようにしないといけない感じになってる。

https://twitter.com/#!/glassonion1/status/100470766931423232

"ゲーム内仮想通貨の値段設定はTier 60(8500円)まで"

Store Kitを使ったアプリ内課金の実装について

実装すると、とても罠が多いみたいですが...

公式ドキュメント

iTunes Connectデベロッパガイド
In App Purchaseプログラミングガイド

参考サイトとか

 

2011年9月14日水曜日

コマンドラインからAppCodeを立ち上げる方法

メニュー -> Tools -> Create Command-Line Launcher...

をクリックすると、コマンドライン用のスクリプト生成画面が表示されるので、好きな名前で登録すればコマンドラインからプロジェクトファイルを開けるようになる。

NewImage

appcode app.xcodeproj みたいなかんじで開ける。
XCodeは関連付けされてるので、open app.xcodeprojでプロジェクトを開ける。

 

2011年9月3日土曜日

Xcode4.1のBehaviorを独自定義して整形スクリプトを走らせたかった

 

Xcode4.1からBehaviorを自分で定義できるようになったため、ショートカットから任意のスクリプトが実行可能になった。

NewImage

Using Uncrustify directly in Xcode 4!のように、整形スクリプトを走らせるようにもできるけど、今開いているタブのファイルだけに対してuncrstufiyを実行させたかった。

上記のprintEnv.shを使って、環境変数の一覧を調べてみたところ、実行対象のファイルパスはふくまれていなくて、プロジェクトを対象にやってる感じになっていた…

XcodeDeveloperPlatformsDirectory:/Developer/Platforms
SHELL:/bin/zsh
TMPDIR:/var/folders/5g/5gEvVawpHWu+RB42rXnkr++++TI/-Tmp-/
Apple_PubSub_Socket_Render:/tmp/launch-3WFq58/Render
USER:azu
COMMAND_MODE:unix2003
SSH_AUTH_SOCK:/tmp/launch-H4Av4Y/Listeners
__CF_USER_TEXT_ENCODING:0x1F5:1:14
XcodeDeveloperDirectory:/Developer
PATH:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin
PWD:/Users/azu/Downloads/ShareKit.0.2.1/0.2.1gm1
XcodeWorkspacePath:/Users/azu/Downloads/ShareKit.0.2.1/0.2.1gm1/ShareKit.xcodeproj/project.xcworkspace
SHLVL:1
HOME:/Users/azu
XcodeProjectPath:/Users/azu/Downloads/ShareKit.0.2.1/0.2.1gm1/ShareKit.xcodeproj
XcodeProject:ShareKit.xcoeproj
LOGNAME:azu
DISPLAY:/tmp/launch-KbbwXZ/org.x:0
XcodeDeveloperApplicationsDirectory:/Developer/Applications
SECURITYSESSIONID:3019c3
_:/usr/bin/ruby

何かいい方法ないのですかね。

Xcode 4.1 for Snow Leopardがインストールできないように見える件

NewImage

Xcode 4.1 for Snow Leopardが公開されています(数日ダウンロードができないトラブルがあった)
snow leopardだとApp StoreのXcodeがダウンロードできなかったので、今まで通りダウンロードしてきてインストールします。

xcode_4.1_for_snow_leopard.dmgというファイルをダウロードして、今までのようにInstallXcode.pkgをインストールしてもそのままではインストールは完了していません。
実際には/Application/フォルダにInstall Xcode.appというファイルがインストールされるだけです。

そのため、Install Xcode.appを実行してインストールすれば/Developer/ディレクトリの方にXcode.appなどがインストールされるようになるみたいです。
(どうしてこんなわかりにくい仕様にしたんだ…)

2011年9月2日金曜日

ShareKitで入力画面なしで投稿させる

ShareKitはTwitterやFacebookやEmailやTumblrなどそのへんのサービスへの投稿をまとめて受け持ってくれるライブラリです。

SHKItem *item = [SHKItem text:[postText text]];
[SHKTwitter shareItem:item];

という感じで、Twitter投稿させたいと思ったとき、shareItemメソッドだと
入力画面がでてから投稿という感じになってしまいます。

入力画面をなしにして、入力をコードで指定して投稿させるにはsendメソッドを使うといいです。

    SHKTwitter *twitter = [SHKTwitter new];
    if([twitter authorize]){
        SHKItem *item = [SHKItem new];
        [item setCustomValue:[postText text]];
        twitter.item = item;
        [twitter send];
    }

shareItemメソッドはログイン状態の確認も自動でやるので、[twitter isAuthorized]しなくてもいいですが、
sendメソッドは投稿するだけなのでログインしていないとエラーになります。
なので、isAuthorizedで確認する必要があるのとログイン処理をするので、[twitter authorize]を使うと楽です。

- (BOOL)authorize
{
	if ([self isAuthorized])
		return YES;
	
	else 
		[self promptAuthorization];
	
	return NO;
}

2011年9月1日木曜日

"Xcodeが予期しない理由で終了しました。" というエラーで開けないXCodeプロジェクトを修復

 

NewImage

XCode4.0.2 for snow leopardを使っていますが、結構な頻度でタイトルのような「Xcodeが予期しない理由で終了しました。」となり、
xcodeprojファイルが開けなくなることがあります。
(ちなみにJetbrains IDEのAppCodeでは開けるという状態)

このプロジェクトの中にある

プロジェクト名.xcodeproj/project.xcworkspace/xcuserdata/ユーザー名.xcuserdatad/UserInterfaceState.xcuserstate

というファイルを削除or移動させれば開けるようになるみたいです。

このファイルはXCode4から追加されたようで、UIの設定を持ってる感じのファイルです。

gitでも邪魔臭いファイルです…
逆に壊れてる状態でもAppCodeで開けたのは、この設定ファイルはXCode専用のものだからのようですね。

 

2011年8月29日月曜日

カレンダーを生成するUIコンポーネントライブラリ for iOS

カレンダーViewを作るのに参考になりそうなものを探している。

devinross/tapkulibrary - GitHub

標準カレンダーライクなUI
カバービューなどいろんなViewを提供してくれるライブラリの一部にカレンダーがある。

Screenshot 8

klazuka/Kal - GitHub

こっちも標準カレンダーライク

Screenshot 9

muhku/calendar-ui - GitHub

DayとWeeklyのViewがあるカレンダー

Screenshot 10Screenshot 11

 

damiandawber/DDCalendarView - GitHub

シンプルな感じのカレンダー実装

Screenshot 12

 

shaokun/SimpleCalendarView - GitHub

結構綺麗な感じのカレンダー
コードも整理されてる。

Screenshot 13

voidparadox/Si-Calendar - GitHub

標準カレンダー風
ちょっとタップのアニメーションとか増えてる気がする

Screenshot 14

iphonecal - iPhone calendar control/iPhone日历控件 - Google Project Hosting

中国語だけど、ちょっと書き換えれば他の言語でも同じ。
drawを多用してる感じのコード

NewImage

 

標準でカレンダーViewを提供されてそうな気がしそうなんだけど、EventKitみたいなAPIぐらいしかないのかな。
他にもカレンダーViewを作るライブラリなどがあったらよろしくお願いします。

 

2011年8月23日火曜日

Appleのアプリ審査ガイドライン、UIWebViewに関係するリジェクト事例

大部分がUIWebViewだけを使うようなアプリに対してどういう審査があるのかを少し調べた。

Appleによる審査ガイドライン

日本語

英文と並んでいて見やすい

via アップル社のアプリ審査基準ガイドライン最新版の和訳を公開しました « ジェネシックスブログ

他の人の訳

審査基準ガイドラインについての私見が書かれていてわかりやすい。

リジェクト理由をいろいろ書いた記事の訳

ガイドラインでUIWebViewに直接関係ありそうな所

  • 2.17
    Apps that browse the web must use the iOS WebKit framework and WebKit Javascript
    ウェブをブラウズするアプリはiOS webkit framework と webkit Javascript を使わなければなりません。
  • 11.2
    Apps utilizing a system other than the In App Purchase API (IAP) to purchase content, functionality, or services in an app will be rejected
    In App Purchase以外のシステムでコンテンツや機能、サービスにアプリ内で課金を行うアプリはリジェクトされます。
  • 12. Scraping and aggregation

    12.1
    Applications that scrape any information from Apple sites (for example from apple.com, iTunes Store, App Store, iTunes Connect, Apple Developer Programs, etc) or create rankings using content from Apple sites and services will be rejected
    アップル関連のサイトの情報をスクレイピングしたり、その情報を使ってランキングを作ったりしたアプリはリジェクトされます

    12.2
    Applications may use approved Apple RSS feeds such as the iTunes Store RSS feed
    iTunes Store RSS feedのような承認を受けたApple RSS feedsは使っても良い

    12.3
    Apps that are simply web clippings, content aggregators, or a collection of links, may be rejected
    ただウェブを切り抜いたり、コンテンツを集計したもの、リンク集のようなアプリはリジェクトされます

リジェクト事例から

通信失敗、エラー時のフィードバックは必須

1.Webサービスと連携しているアプリで、審査時にWebサービスとの間でエラーが起きてしまい処理が完結できなかったのでrejectされました。

通信エラー時に簡単にデータが失われないようにしてリトライできるようにしておくこと。特にWebViewをembedしてるアプリだと気を遣う必要はありそうです。

2.同様にWebアプリと連携する場合は、ネットワークが繋がらない際のエラー処理に注意を払う必要があり、エラー時の動作が適切ではないという指摘を受けたこともあります。

アプリ起動後に通信エラーになった場合の動作確認は、地下鉄や半地下の事務所などでテストするとやりやすいかも。

最低予算1万ポイントで。iPhoneアプリの審査でリジェクトを食ら.. - 人力検索はてな

 

・リモート画像を表示する画面で、ネットワークに接続されない状態で画面を開いてもなにもおきません。

これがヒューマンインターフェースガイドライン違反なので、ネットワーク接続が必要な旨=エラーである旨を表示する必要があるとのことです。

僕の場合はUIAlertを使ってアラートを出しまして通過しましたが、特にアラートじゃなくても通知できれば問題なさそうです。

最低予算1万ポイントで。iPhoneアプリの審査でリジェクトを食ら.. - 人力検索はてな

 

WebViewを組み込みのアプリで、ページの読み込み中に「Now Loading..」などのメッセージを表示するようにしないと、rejectされます。

ネットワークに接続されていない環境だと、永遠にWebページが表示されず、フリーズしたように見えるためです。

テストするときは「機内モード」をオンにすれば簡単だよ、とアドバイスを受けました。

ちなみに、以下がrejectされたアプリです。

http://jp.youtube.com/watch?v=K5ZoBXDLi1M

最低予算1万ポイントで。iPhoneアプリの審査でリジェクトを食ら.. - 人力検索はてな

 

2. AirPlane モードで、期待されているように動かない

ちゃんと AirPlane モードでも動作することを確認しているのだなーと。
3. ネットにつながってないときに同期ボタンを押してもなんの反応もないので、なんらかのフィードバックをユーザに返すようにしなさいね、とのこと (Alert とか)

Alert だされるとうっとうしいので、何も表示しないようにしていたんですけど、何らかのメッセージを bottomBar に表示する、とかでも良さそうです。

最低予算1万ポイントで。iPhoneアプリの審査でリジェクトを食ら.. - 人力検索はてな

機械的な判定により弾かれる事例

結局リジェクトされてた理由がよくわからない例

Webサイトを表示するだけのアプリの事例

このへんの境界線があやふや

12.3 Apps that are simply web clippings, content aggregators, or a collection of links, may be rejected
ただウェブを切り抜いたり、コンテンツを集計したもの、リンク集のようなアプリはリジェクトされます

アップル社のアプリ審査基準ガイドライン和訳 - Google ドキュメント

アドレスバーから任意のURLを入力できるようなものは基本的に17+のレーティングにする必要がある。
Google検索ができるようなアプリも多分同じような扱いになりそう。
(似たようなアプリのレーティングをチェックするのがよさそう)

UIWebViews

アプリの持つWebViewが制限なくインターネット(何があるか分からない闇の世界だ)へアクセス可能な場合、自動的に17+のレーティングを義務づけられる。最初からあるSafariになぜ未成年者がアクセスできるのかは謎だ。どうやらそういうものらしい。

[訳] App Store Rejection Reasons | iPhone Development Blog - iOS 開発ブログ Natsu's note

その他

他の場合にも関係するが、プロモートだけを目的としてアプリはリジェクトされる。

他にもUIWebViewに関する事例や経験やリジェクトについての文章などがあったらお知らせください。

2011年7月30日土曜日

PHP5.4でビルトインウェブサーバーを使って反復実行環境の構築

PHPを勉強してて、コマンドラインで完結するようなphpファイルならあまり問題ないのですが、Webブラウザからアクセスして動作を確認する場合は
Apacheなどのローカルサーバに依存してて、特定のディレクトリに集める必要などがあって面倒だった。

NewImage

PHP5.4でビルトインウェブサーバーが導入されたので、phpからサーバを立ち上げてできるため、VirtualHostディレクティブなどを設定しなくても、
コマンドラインからphpを叩くだけでlocalhostにアクセスする環境が作れる。

PHP5.4はまだ正式版ではないので、自分でソースをダウンロードしてビルドする必要があります。

$ wget http://snaps.php.net/php5.4-latest.tar.gz
$ tar -xzvf php5.4-latest.tar.gz
$ cd php5.4-201107282230/
$ ./configure
$ make

makeまでにして、installはしないようにしています。

./sapi/cli/php -v
PHP 5.4.0alpha3-dev (cli)

CLIのphpが実行できるので、PHP: ビルトインウェブサーバー - Manualを参考にサーバーを立ち上げます。

準備ができたところで、こっから本題です。

自分はPHPStormを使っているので、External Toolからphpのコマンドを叩いて、
指定のファイルがディレクトリをrootにしたサーバーを立ち上げるように設定しています。

NewImage

☑Open consoleにチェックすると、PHPStorm内でコンソールを開いてコマンドを叩きます。この方法で開くとログもPHPStrom内からみられるので便利です。
プロセスの停止もPHPStorm内からプロセスを殺せます
Program: 先ほどコンパイルしたphpバイナリへのパス
Parameters:  -S localhost:8000 -t $FileDir$
これは PHP: ビルトインウェブサーバー - Manualを見るとわかりますが、
ポート番号8000で、ファイルがあるディレクトリをrootにしたサーバが起動するようにした引数です。

あとは、ブラウザで、http://localhost:8000/file.php にアクセスすれば結果が見られて確認などが便利。
同じように External Toolからopenするのもいいかもしれないです。

NewImage

$php -S localhost:8000 -t /path/to/dir/ && open http://localhost:8000/file.php

みたいに、サーバの起動と同時にブラウザも開くようにしたかったけど、やり方がよく分からなかった。

参考

2011年7月29日金曜日

githubからclone時にerror setting certificate verify locationsがでる

X / _ / X < git clone https://github.com/niklasvh/html2canvas.git
Initialized empty Git repository in D:/MyDocuments/Dropbox/workspace/toybox/html2canvas/.git/
error: error setting certificate verify locations:
CAfile: /bin/curl-ca-bundle.crt
CApath: none
while accessing https://github.com/niklasvh/html2canvas.git/info/refs

https接続するときに証明書のエラーになってるのが原因みたい。

$ git config --system http.sslcainfo \\bin\\curl-ca-bundle.crt

Windows 7 x64で、上のようにコマンドを打ったら、c:/Program Files (x86)/Git/bin/curl-ca-bundle.crt を使ってくれるようになるみたい。git config -l で確認してみると、設定値が以下のようになった。

http.sslcainfo=\\bin\\curl-ca-bundle.crt

なんで、今頃なったんだろ…

2011年7月22日金曜日

TDDの良い点、難しい点

Outsider's Dev Story :: TDD를 한달여정도 해보고 나서....よりメモ

JavaにおけるTDDを一月程実践しての話らしい

良い点

  • 開発の速度が遅くなるということはなかった
    テスト作成のために時間が減るという感じはなく、今までスコップ作業していた部分が自然に流れるようになった
  • テストを先に作成してからどう実装するかを考えると、開発の目的がはっきりした。
    理解しながら開発ができる
  • 思わぬタイミングで表示されるred(テストが失敗したときに出る赤いバー)はストレスではなく安心を与えてくれた
  • リファクタリングが非常に安心しながらできた
  • given / / when / / thenテンプレートは便利だ
    http://doortts.tistory.com/169
    テストの構造化ができてよみやすくなった

難しい点

  • TDDによってデザインがよくなるわけではない
    TDDによってこれが自動的に得られるわけではなく、やはり多くの経験と知識が必要です。
    デザインが悪いのか、テストケースが未熟なのかを判別するのが困難だった
  • テストする ということは思ったより難しい
    特にUIに関係するとどうテストするのかが難しいと感じた
  • 依存性のある部分のテストはやはり難しい
    Mockを使おうとしたけど、テストに慣れてないと難しい
  • ますます混乱するFixture
    全体的に共通のFixture テストがあまりなくて、テストケースごとにFixtureをとっていくことになった、テストが長くなり複雑になってしまった
  • リファクタリング中にテストケースを作成する自体になると困り果てる
思ったよりは順調に適応できてメリットなどを感じられるようになった。
TDDは習慣しなければならないと思った。


====

たぶん、Google先生で読むとそんな感じ。




2011年7月20日水曜日

手軽にObjective-Cのコード実行出来る方法を求める

手軽にObjCのコードを実行できる環境が欲しい。。

今やっているのは次のような感じです。
IntelliJのAppCodeを使っていますが、XCodeプロジェクトを作ってるだけなので、XCodeでも同じことができます。

New ProjectからCommand Line Toolを選んで


201107202050.jpg

TypeはFoundationを選択してFinish


201107202051.jpg

あとはmain.mファイルをいじって実行をするだけ。


201107202052.jpg

でも、この方法だと別のことを試すのにまた新しいプロジェクトを作らないと行けないのが何か嫌な感じ。
testフォルダに別のmain関数持ったものを作っても、ビルドするときにmainが重複してるからダメだしファイルを対象にして実行できるといいんだけどなー。(Vim + quickrunみたいな手軽な環境が欲しい)

Vim+quickrunでC言語の勉強環境 | MemeTodo

なぜかMacvimでvundleとかがエラー吐いて動かせないので、しばらくこれで。

http://twitter.com/#!/azu_re/statuses/93360504067727361
201107202059.jpg

2011年7月8日金曜日

Vim+quickrunでC言語の勉強環境

Vimとquickrunは各自適当に入れておく。

自分はVundleを使って入れています。

" Quick Run *vimproc
Bundle 'thinca/vim-quickrun'

Windows7なので、MinGWでgccを使えるようにします。
MinGWでC(C++とかも選べる)のコンパイラーを適当な場所(自分はD:\Programs\)にインストールしたら、パスは自動で通してくれないので自分で通す必要があります。
自分はRedmond Pathを使ってパスを通しました。(D:\Programs\MinGW\bin に対して通す)
そうすれば、コマンドプロンプトからgccが使えるようになると思う。

Quickrunには最初からgccのプリセットが入ってるので\+rをCのファイルで実行すれば、自動的に一時ファイルを作って実行できる

分割位置の設定もするといいです

学習用C言語開発環境 Ver 0.0.9.0も便利な気がするけど、何かプロジェクト単位なので少し扱いにくい。

RPGツクールから見るユーザー視点の制作物

SFCなど出ていたRPGツクールのカセットを買ってきて、その中にもしデータが残っていたらそれをプレイするという実況動画シリーズがニコニコ動画にあります。

これの面白い所は、ソフトを売った人はそれを他人に見られる事を想定してので(データが残ってる所とか)、中途半端なゲームだったり、カオスなゲームだったり、壊れてるゲームだったりいろいろと面白いものがでてきます。 (実況自体は成長しないのでアレなのですが…)

これを見てて(初期から見てたので相当前の話だけど)、よくあるミスに「RPGツクール1でカウンター越しに会話ができるようにするためには、カウンター自体にイベントをつけないといけない。」という罠にはまっているのを見かけます。

  +
  |
  |
 x|p
  |
+-+

で見ると 、カウンター内にいる人xにプレイヤーpが話しかけるには、xに会話イベントをつけるのではなくて、カウンター自体に会話イベントをつけないといけないというちょっとアレな仕様になっている(2とかで想像通りの挙動になるけど)


このおかしな挙動はテストプレイをすれば気づく可能性は高いけど、そこに至ってない(投げ出すも含めて)ユーザーの作品も多かった。
なぜこういう事が起きるのかを教訓的に考えてみると、ユーザーが必ずしも制作者という意識(プレイヤーがプレイできるものにする)を持って作るわけではなく、あくまで作る事だけを考えて満足してしまっている事がある。


RPGツクールの場合、こうやって公開される事が希なので別に問題ないけど、CGMなどそういう類いのものでも同じようなユーザー心理が働いてる可能性は存在する。 そのような作品が多く公開された状態になるのはサービス側にとってもよくないし、何とか防止する方法が必要になる。
つまり、RPGツクールを作った人とRPGツクールで作る人には何かしらの齟齬があったりするので、ユーザーに何かを作らせようとするものは、そういう齟齬を減らす工夫を考えるとよりよりサービスになるのではないかなと思った。


まあ、なんでこんな文章を書いたのかというとRPGツクール1でカウンター越しイベントは普通にバグっぽいよなって事を書きたかっただけです。はい。

2011年7月6日水曜日

Janetter上でもThinkPadのトラックポイントスクロールをできるようにした

Janetterはハッシュタグと平行して見られたりして、イベントの時とかは便利なので使ってました。でもThinkPadのトラックポイントでスクロールができないのが微妙に不便でした。
ThinkPadのThinkPointでスクロールできない

下記の記事を参考に、tp4table.dat に Janetter.exe を追加してください。

Office2007でThinkPadのThinkPointがスクロール不能の回避
http://d.hatena.ne.jp/teiiz/20070214/1171428196

※tp4table.dat が見つからない場合は、C:\Program Files\Synaptics\SynTP にあります。
TP4scrol.dat 及び TP4table.dat に追記してください。
※Win7,Vistaで書き込み権限がない場合、C:\Users\{User名}\AppData\Local\VirtualStore\ 内に
ファイルが書き出され、実際のファイルが更新されていない可能性があります。ご注意ください。

のように TP4table.dat に設定を追加して、ThinkPadを再起動すればスクロールできるようになります。(C:\Program Files\Synaptics\SynTP にあった)

; Janetter
*,*,Janetter.exe,*,*,*,WheelStd,0,9

TP4table.dat に上記を追記した。

2011年7月5日火曜日

IndexedDBについて

IndexedDBはChrome12-,Firefox4-が今のところ対応している

FirefoxではIndexedDBを使う際にはローカルデータのやつみたいにユーザーの許可が必要になる。(http://twitter.com/azu_re/statuses/87887746680627201)

image

以下、使い方やサンプルなど

IndexedDB - MDN Docs

一番よくまとまっている。
APIの使い方から対応状況とか

IndexedDB Implementations

APIごとサンプルが用意されていて、その場で実行できたりするのでIndexedDBを把握するのに便利
Google Code Playgroundみたいな感じ

image

HTML5 Rocks - A Simple TODO list using HTML5 IndexedDB

シンプルなTodoアプリを作るチュートリアル

IndexDB Demo - Version 1.0

こちらもIndexedDBを使ったサンプル。
key=value

2011年7月4日月曜日

Twitterのリアルタイム検索ができるサービス

Google リアルタイム検索が死んでしまってるので、代替になりそうなサービスを探してみる
Googleリアルタイム検索は質と言うよりは量が大事だったので、Firehoseの契約をしているかとか曖昧な単語でも検索できたり、時間軸が見られるのが結構よかった。(後、日本語、英語の切り替えが楽だったのも)

Twitter、リアルタイム検索スタートアップに消防ホースを開放とか探せば他にもありそうだけど、、、
何か良い感じのサービスはないのかな。。

追記: やっぱりFirehoseの契約が切れたので中断したみたいだ。

2011年7月3日日曜日

co.ccドメインがGoogle検索に表示されない件

site:co.cc - Google 検索を見ると分かりやすいですが、Googleがco.ccのドメインなサイトを検索結果から丸ごと消えるようにしたみたいです。

このサイトも.Co.CC+Bloggerで運営していたので、検索ハブされまてたので、efcl.info以下に引っ越しました。それに伴って今までのRSS購読やはてブなども死んでいます。(Bloggerにリダイレクト機能がないので…)
多分、これで固定になると思う。すみません。

2011年7月2日土曜日

style + contenteditable = Live style sheet editing

style要素とcontenteditableで入力したCSSを適応 - jsdo.it - share JavaScript, HTML5 and CSS

入力したCSSがその場で適応されるやつです。 (Shift+Enterで改行)
style要素にcontenteditable属性をつけた中身にCSSを書くと内容が適応されるのを利用しています。

CSSのデバッグなんかに便利な場合があるのかな。
普通にFirebugとかでもいいような気がしないでもないけど。

contenteditable + DOMCharacterDataModifiedでIME入力(変換)中のイベントも拾う

IME入力(変換)中のイベントも拾う - jsdo.it - share JavaScript, HTML5 and CSS

タイトル通りでそれ以上でもそれ以下でもないです。

FirefoxとChromeで動作確認できた。
IEは9からDOMCharacterDataModifiedをサポートしてるらしいです。
Operaはよく分からない

DOMCharacterDataModifiedはMutation Events の一つらしいですが、これ系はいつも情報が少ない… 使い道があるのかも微妙

一応元ネタ

関係しそうなの

全く関係ない事

このサイト、悪名高いco.ccドメインを使っていたので(tkドメインもそういう感じに使われがちだね)、検索ハブされたりするのはさすがに良くないので、efcl.info以下に引っ越しました。
なので、RSSやはてブとか吹っ飛んでいます。すいません。

2011年6月28日火曜日

Githubのrawリンクも変更された

gistの変更に追従というか合わせて、GithubのrawファイルのURLが変更された。

たとえば、今までのようなURLだと

https://github.com/azu/OAuth-for-Greasemonkey/raw/master/GMwrap.js

下のように、rawをサブドメインとしたURLに302リダイレクトされる。

https://raw.github.com/azu/OAuth-for-Greasemonkey/master/GMwrap.js

302というのも何か気持ち悪いけど、GMwrap.js at master from azu/OAuth-for-Greasemonkey - GitHubから見られるrawのリンクは未だに古いまま。

これの影響で、リダイレクト先を自動で取得してくれないものは今までのURLだとエラーになる。
Greasemonkeyの@requireとか@resourceとか…

2011年6月26日日曜日

タブに重複ファイル名がある場合に見分けられるようにするJetBrainsプラグイン

TabFolderというJetBrains系IDEで動くプラグイン。
WebStormで動かしてるけど、どのIDEも対応している。

インストールすると、プロジェクト内に同じファイル名のものがあって、それを両方ともタブに開いた際にフォルダ名をタブに追加してくれる。
何か似たようなプラグインを見た気がするけど、WebStormだとこれしかないような気がする。

image

そのうち標準で入ってそうな機能でもある。

2011年6月25日土曜日

Firebugのconsole.log()の返り値をそのまま使ってはいけない

以前Twitterで書いたけど、記事にするの忘れてたので。

そもそもはconsole.log()の返り値がundefinedだと思っているという前提みたいなものがあるので、気にならない人は全く気にならないと思います。

まず、console.logの返り値を使ってしまうとはどういう状況かというと

function mimi(arg){
if(!arg){
return console.log("引数ないよ!");// return&メッセージ出すと便利
// だけどこのときのreturnされるのはfalsyではない場合がある
}
// 処理
}
var res = mimi();// falsyな値が返ってくると思ってしまう
// 実際にはresに _firebugIgnore が返ってくる
if(res){ // resがtrueになって意図とは異なる可能性
// ほげ
}

このように、引数が足りないから空のreturnして関数を抜けることがありますが、こういうときに同時にメッセージを出力すると便利です。
だけど、Firefox4+Firebug1.7以降だと、console.logの返り値は_firebugIgnoreというものになっているため、上のように書くと意図とは異なる動作になる事があります。

回避法は単純にconsole.logの返り値がundefinedなどのfalsyと保証されている訳ではない事を理解して使えばいいので、いろいろやり方はある。

以前いろいろ書いたけど、JavaScriptでのlogデバッグ関数 | MemeTodoのようなlog関数を通すのが簡単で安全な気がします。

なんで_firebugIgnoreなんてものを返すのかは多分下あたりに。

JavaScriptでのlogデバッグ関数

を見て何となく書いた。

Greasemonkeyだとこういうのをよく書いてて、consoleは直接使わないでlog関数経由で出力してた。

function log(m) {
if (unsafeWindow.console) {
unsafeWindow.console.log.apply(this, arguments);
} else {
console.log.apply(this, arguments);
}
}

わざわざunsafeWindowと分けて書いてるのは、たまにconsoleが無いとか言われることがあったため。

似たような方法で、log関数でデバッグなどをするのは良いけど、公開するときにそのlog関数を除去するのは面倒なので、DEBUGという変数で出力するか否かを変更できるようにしたものも使ってた記憶がある。
var DEBUG = true;// デバッグ関数を切り替え
// DEBUG - true
function log(m) {
if (typeof DEBUG !== 'undefined' && DEBUG) {
if (unsafeWindow.console) {
unsafeWindow.console.log.apply(this, arguments);
} else {
console.log.apply(this, arguments);
}
}
}
これと似たようなもので、上のだと毎回判定しているのが何か気に入らなくてクロージャーで、DEBUGの判定を一回だけにするものも書いた(これはGreasemonkeyじゃなくても使える)
var debug = (function() {
var DEBUG = true;// デバッグ関数を切り替え
if (DEBUG) {
return function() {
console.debug.apply(this, arguments);
};
} else {
// コール可能でできるだけコストが低いものを考える
return function() {
// do not anything
};
}
})();

DEBUG = false;の際はコールしても意味ないダミー関数が呼ばれるようになる。
さっきのと合わせて、GreasemonkeyのunsafeWindowのコードを入れると以下のような感じか

var debug = (function() {
var DEBUG = true;// デバッグ関数を切り替え
if (DEBUG) {
return function() {
log(arguments);
};
} else {
// コール可能でできるだけコストが低いものを考える
return function() {
// do not anything
};
}
function log(m) {
if (unsafeWindow.console) {
unsafeWindow.console.log.apply(this, arguments);
} else {
console.log.apply(this, arguments);
}
}
})();

合わせてこれも

2011年6月24日金曜日

JavaScriptのパッケージ管理システムのEnder.jsを見た

Ender - the no-library library.というJavaScriptのパッケージ管理ライブラリみたいなものをちょと触った。

node.jsが必要で、npmでインストールする
最近、JavaScript関係でもNode.jsを使ったものが多いので、Windowsでも使えるようにWindowsからVM上のLinuxをSSH経由で利用する開発環境の構築 | Web scratchとかCygwinで準備しておいた方がいい気がする(そのうちWindows版Nodeでると思いますが。Porting Node to Windows With Microsoft’s Help « node blog)

$ npm install ender -g

ender.js自体はパッケージ管理、ビルドなどのコマンドラインツールだと思う。
デフォルトでいくつかJavaScriptパッケージ(ライブラリともいう)が入ってる。
ender build でパッケージをビルドして、ender.min.jsとender.jsが生成される。

$ ender build scriptjs backbone
ender infoでアクティブなパッケージ群が表示できて、結構面白い。

X/ _ / X <  ender info
Welcome to ENDER - The no-library library
-----------------------------------------
Your current build type is "build"
Your current library size is 7.9 kb

Active packages:
└─┬ jeesh@0.0.5 - The official starter pack for Ender.
├── domready@0.2.4 - bullet proof DOM ready method
├── qwery@2.1.2 - blazing fast CSS1|2|3 query selector engine
├── bonzo@0.6.1 - Library agnostic, extensible DOM utility
└── bean@0.1.9 - an events api for javascript

パッケージを追加するには、ender addでできる。
ender addしたときに、既にビルドしたender.jsなどがあったら自動で更新されたりしてるのが面白い。

X/ _ / X <  ender add underscore
Welcome to ENDER - The no-library library
-----------------------------------------
installing packages: "underscore"...
this can take a minute...
successfully finished installing packages
assembling packages...
ender.js successfully built!
ender.min.js successfully built!
X / _ / X < ender info
Welcome to ENDER - The no-library library
-----------------------------------------
Your current build type is "build"
Your current library size is 10.7 kb

Active packages:
├─┬ jeesh@0.0.5 - The official starter pack for Ender.
| ├── domready@0.2.4 - bullet proof DOM ready method
| ├── qwery@2.1.2 - blazing fast CSS1|2|3 query selector engine
| ├── bonzo@0.6.1 - Library agnostic, extensible DOM utility
| └── bean@0.1.9 - an events api for javascript
└── underscore@1.1.6 - JavaScript's functional programming helper library.
パッケージから取り除くには
ender remove

を使う。
パッケージごとにバージョンを指定したりもできるみたい

ender set bean@0.0.3

使えるパッケージ(ライブラリ)はEnder.js - The open submodule libraryとかに書いてあるのとか、自分で追加したりできるんだと思う。
Ender.js - The open submodule libraryは小さな機能集合で、全部入れればjQueryと似たような機能はだいたいあるような気がする。underscore.jsとかbackbone.jsとかもパッケージに追加できたりして、好きな機能だけが入ったものをビルドできたりして仕組み的にはいいかもしれない。
(内部のコードがどうなるかがアレですが)

最初はスターターパックとか書かれている

のパッケージをいれたJEESHとか言うので試してみてる。(このJEESH自体はCDNでホスティングされてるみたい)
DOM系でjQueryライクなものを集めた感じ。

X / _ / X <  ender -b jeesh
Welcome to ENDER - The no-library library
-----------------------------------------
installing packages: "ender-js jeesh"...
this can take a minute...
successfully finished installing packages
assembling packages...
ender.js successfully built!
ender.min.js successfully built!
X / _ / X < ender info
Welcome to ENDER - The no-library library
-----------------------------------------
Your current build type is "build"
Your current library size is 7.9 kb

Active packages:
└─┬ jeesh@0.0.5 - The official starter pack for Ender.
├── domready@0.2.4 - bullet proof DOM ready method
├── qwery@2.1.2 - blazing fast CSS1|2|3 query selector engine
├── bonzo@0.6.1 - Library agnostic, extensible DOM utility
└── bean@0.1.9 - an events api for javascript

underscore.jsにDOM系のものも混ぜたいとか思ったら、触ってみると良さそうな気がする。

$.map(['a', 'b', 'c'], function (letter) {
  return letter.toUpperCase();
}); // => ['A', 'B', 'C']

$.uniq(['a', 'b', 'b', 'c', 'a']); // => ['a', 'b', 'c']

みたいな感じで、underscore.jsも$から使えるようになる。

まだ実際にコード書いてなくて、パッケージ管理としての機能を見てだけなので、使ってみてどうなのかは分からない。

小さな機能別のライブラリを集めて使うってので、microjsを思い出した。

2011年6月23日木曜日

<img src="" /> とした時に起きる、ブラウザ間での動作の違いについて

<img src="" /> としたときの動作をブラウザ別に並べよ。(一つのブラウザにバージョン別の挙動を書いても良い)
http://twitter.com/azu_re/status/83761909039505408

というので、img要素のsrc属性値を空にしたときの動作について、以前調べたものを今更だけど置いておきます。
調査目的は表題とは若干違って、<img src="http://~" /> という要素のsrcを空にした場合、その通信は停止するのかという事を知りたくて調べてました。
04WebServerというローカルサーバーを使って試していたので、Apacheなど一般的なものだと異なる可能性も捨てきれませんが参考程度に。
バージョンも古い事に注意してください。(おそらく動作は異なるように修正されている気がします)


2010年12月1日

目的:XHRDOMにより画像を読み込むことができるが、XHRabort()DOMsrc=""とすることで通信が本当に停止しているかを確認する。

  • Firefox 3.6.12
  • Chrome 7.0.517.44
  • Safari 5.0.3
  • Opera 10.63

XHR

abotによる停止

onabort

接続が切れてるか(サーバーのログから見る)

IE6-8

発生しない*1

500, Internal Server Error データ送信中に切断もしくはネットワークエラーが発生しました(以下500 Internal Server Error)

Firefox

発生

500, Internal Server Error

Chrome

発生

500, Internal Server Error

Safari

発生

500, Internal Server Error

Opera

発生しない

500, Internal Server Error

*1 IE6-8XHRにはonabort実装されていない

プロファイラを利用して確認

clip_image001

しかし、abort()後にxhr.readyState == 4となるため、自分でabortフラグを管理することでabort()によってreadyState==4 になったことがわかるのでonabortの代用は可能

DOM(Imageオブジェクトを使用) - example.htmlで実行した場合

停止(srcを空に)

onerrorイベント

空の場合の読み込み

接続が切れてるか(サーバーのログから見る)

IE6-8

発生

example.html

500, Internal Server Error

Firefox

発生しない

読み込まない

500, Internal Server Error

Chrome

発生

example.html

500, Internal Server Error

Safari

発生

example.html

500, Internal Server Error

Opera

発生しない

読み込まない

500, Internal Server Error

どちらの方法もサーバから切断しているため、通信は停止できたと思われる。
が、
IE6-8ではimg.src = "";としたときに、そのスクリプトがあるページ( example.html)を読み込もうと無駄な通信をしてしまう。

これは、属性値が空の場合の挙動がブラウザの実装依存になっているため、ブラウザ間で挙動の違いが存在し、属性値が空をページそのものと解釈して読み込み処理が起きてしまっている。
2010年のごく最近にWHATWGでの議論により、属性値が空の場合は読み込まれないことが適切という結論がでたらしい。

よってHTML5ES5ではこの結論を追従した実装になっているだろうという話。
下の記事によると
Firefox3.5Opera以外のブラウザで属性値が空の場合に無駄な読み込みが発生しているので、結果と一致している。

つまり、<img.src="" />としたことで、画像の読み込みが停止できているように見えるが、IEの場合には自分がいるページを読み込む無駄な通信が生まれてしまっている。Firefox以外ではonerrorが発生していることから、errorを発生させて画像の読み込みを停止させているのではないかと推測できる。(追記:この辺推測なので、正確性は保証されません)

DOMのImageオブジェクトでの読み込み停止は、実際にはエラーにより停止しているというのが近いのかもしれない。
window.stop()によってDOM(Imageオブジェクト)での読み込みも停止できるが、他の通信も止まる。(ブラウザによって異なるかも)

2011年6月22日水曜日

IE9関係の翻訳記事がいろいろ更新されてた

何かいろいろ一気に更新されてたので、興味あるのを取り出してみた。

Internet Explorer ブログ (日本語版) - Site Home - MSDN Blogs から

Internet Explorer デベロッパーセンター:MSDN オンライン更新情報(RSS)から

全部取り出した訳じゃないけど、それでも10個ぐらい一気に更新されてた。
これぐらい一気にやるならどっかに更新内容だけをまとめた記事とかほしい。

こういう翻訳記事を書いてくれてるブログとか(公式以外でも)、他にあったりするのかな。

2011年6月21日火曜日

Web開発に使えそうな気になるツール、ソフトウェア

何か気になりますね。そんなツールなど。

HTTPモニタリングやプロキシなどのジャンル、CocProxyで有名なローカルファイルの置換機能など何かと便利なもの。
Fiddler勉強会開かれるといいですね。

dynaTrace AJAX EditionはJavaScriptの実行順とかパフォーマンスチェックとか、関数の呼び出し回数みたいなプロファイリングがかなり詳細にとれるのでとりあえず触るといい。
元々IE向けのソフトウェアだったので、IEでのデータがかなりとれてとてもよいソフトウェア。
FIrefoxにも最近対応しているが、Firefox4とかそのとき安定したバージョンでないと動かない事があるきがする(理由は多分 http://twitter.com/azu_re/status/79839998479826945 )

メモリリークとかの調査。
JavaScript Memory Validatorは使ってる人見たことないので気になる。
Webkitは--enable-memory-infoでJavaScriptから、JavaScriptのヒープサイズなどを取得できたりするし、Web Inspectorにもその辺の機能が組み込まれてきている。

Firefoxもメモリ情報を取得できるようになってきて(特権機能=通常のWebサイトのようなコンテキストからは無理)、少し前まではしょぼかったけど、今はWebkitと同じようにJavaScriptのヒープサイズなどを取得できるようになってきている。
(取得というと何か変な気がする、about:memoryにそういう情報が表示されるようになったって感じか)

ChromeはChrome OSとの関係でメモリとかプロセスとかそういう関係のものをどんどん載せている気がする。最近(Chrome14ぐらい)、chrome://taskmanager というプロセス管理画面ができてた。

ちょっと外れるけど、そういうChromeの機能はabout:からchrome:// という感じになっているみたい。

about:がchrome://version、about:flagsがchrome://flagsに
Google Chrome開発版が14.0.794.0にメジャーアップデート #chromeJP | UNDAKOVR Blog

自分はあまり低レイヤーに詳しくないので、こういう今まで見えにくかったものも見えるような方法がでてきてると思うので、詳しい人はどんどん触れていってほしいですね。

IEとかでも、下記のブログ記事などは全く知らないことばかりだった。

try...catchとErrorオブジェクト

基本的なtry...catchの書き方
try {
    // Code
} catch (varName if condition) { // Mozilla extension; optional
    // If exception thrown which matches condition
    // in try block, execute this block
} catch (varName) {              // Optional
    // If exception thrown in try block,
    // execute this block
} finally {                      // Optional
    // Execute this block after
    // try or after catch clause
    // (i.e. this is *always* called)
}
Firefoxはcatch内でifを使う特殊な書き方ができる。
コード全体をtry...catchしたいーなんて思ったときはwindow.onerrorを使った方がいい
サイ本にもwindow.onerrorを使ったエラーキャッチ(回数制限つける)するものが書いてあった。
// Display error messages in a dialog box, but never more than 3
window.onerror = function(msg, url, line) {
    if (onerror.num++ &amp;amp;amp;lt; onerror.max) {
        alert("ERROR: " + msg + "\n" + url + ":" + line);
        return true;
    }
}
onerror.max = 3;
onerror.num = 0;
いつtry...catchするか、という話が結構難しい感じがする。
JavaScriptだとファイルを読み込むとか、メモリを解放するとかそういう話を直接扱うことはまだ余りないので、使いどころが何か難しいし、いろん なところでwithなどと一緒にパフォーマンスを悪くする要因と書かれたりするので、全くtry...catchしてないコードもよくある。
使うべき所の一つとしてはtry~catch文の正しい使い方 - 素人がプログラミングを勉強するブログを見ていて思ったけど、XPathはなぜか静かに死ぬことがあって、そういう時はどこが悪いのかを見つけるのが大変になるので、エラーハンドリングが大事。 というのも、XpathをGreasemonkeyでのスクレイピングでよく使っていて、サイトの仕様変更によってそのXPathが間違いになる事があって原因究明が大変だった体験などもあるので、経験則的にXPathは気を遣う。
(それ以前の話としては、普通のWebサイトではtry~catch文の正しい使い方のようにユーザー入力を直接セレクタに使うのはnew XSS pattern with jQueryのように危険な場合があるので、try...catchしようがやめておいた方がいいと思うけど)

try...catchが使いにくいって思うのには、どれが例外を発生するかを知っておく必要があるところが大きい気もする。
後、普通にコードを書いて例外が発生しても、それはtry&error方式で直せるのであえてtry...catchするのは避けてしまう。
なので、ユーザーの入力値を元にするもの、外部サイトAPIなどの変更可能性が存在する場合、エラーが発生しても握りつぶしておきたい場所、など使われる場所はある程度決まってくるような気もする。
try...catchの経験不足なので、まだ使いどころをあげきれない。
完全に余談だけど、try...catchを書くときに、後からtry...catchを書き足して囲むみたいな事になる場合が多くて、そういう時にWebStormのSurround With...が便利。
Errorオブジェクト
また、try~catch文の正しい使い方の話に戻るけど、try...catchで黙ってエラーをつぶすとデバッグが大変なので、自発的にthrowをしてエラーを投げた方がいい。catch内でthrowする場合はErrorオブジェクトがあるので、それをthrowするだけでいいけど。
下のように、try...catch以外の場所でthrowする場合はerrorオブジェクトを作ってそれを投げた方がいい。
function dosomething(arg){
    if(!arg){
        throw new Error("引数がありません");
    }
}
というのも、throw "文字列"; などのようにErrorオブジェクトじゃないものもthrowできるけど、デバッガーなどに渡す情報に行番号などがないので、errorオブジェクトを作って投げた方がデバッグしやすい。
おまけ: try...catchのスコープについてなど

2011年6月20日月曜日

走査しながらremove,deleteする時にはまること

また、JavaScriptのremove系メソッドではまったので記録
CSSルールを削除するdeleteRule(idx);
var ss = (function(ss) {
    var dss = document.styleSheets;
    var getRule = function(stylesheet) {
        return stylesheet.cssRules ? stylesheet.cssRules : stylesheet.rules;
    }
    // 全てのcssRuleに対して、iteratorを処理する
    var forEachRule = function(iterator) {
        var some = Array.some;

        return some(dss, function (styleSheet) {
            return some(getRule(styleSheet), function (cssRule, idx, sheet) {
                iterator.call(styleSheet, cssRule, idx, sheet);
            });
        });
    }
    var deleteRule = function(matchSelector) {
        // 引数なし or * の場合、全てのruleを削除する
        if (!matchSelector || matchSelector === "*") {
            matchSelector = true;
        } else if (typeof matchSelector === "string") {
            matchSelector = new RegExp("^" + matchSelector + "$", "i");
        }
        // iteratorを作りcssRuleごとに処理させる
        var iterator = function(cssRule, idx, sheet) {
            var selectorText = cssRule.selectorText;
            if (!selectorText) {
                return;
            }
            var stylesheet = this;
            if (matchSelector.test(selectorText)) {
                //console.log(stylesheet, selectorText, cssRule, idx);
                stylesheet.deleteRule(idx);
            }
        }
        forEachRule(iterator);
    }
    return {
        deleteRule : deleteRule
    }
})(ss || {});
ss.deleteRule(/\.[fc]\d+/i); 
という感じで、渡した正規表現(文字列とかでもいけるようになってるけど工事中)にマッチするセレクタを持っているなら、そのCSSルールを削除する関数を書いていた訳だけど、どうも中途半端に消えたりしていて動作がおかしかった。
コンソールを見てると、1個飛びで消えていたりしたので、replaceChildの注意点 - prog*sigを思い出してた。上の書き方だとsomeで0から順番に走査していたので、deleteRuleする度にindexがずれるので、おかしな結果になっていた。
なので、forで後ろから回すようにした。
var ss = (function(ss) {
    var dss = document.styleSheets;
    var getRule = function(stylesheet) {
        return stylesheet.cssRules ? stylesheet.cssRules : stylesheet.rules;
    }
    // 全てのcssRuleに対して、iteratorを処理する
    var forEachRule = function(iterator) {
        var some = Array.some;

        return some(document.styleSheets, function (styleSheet) {
            var Rules = getRule(styleSheet);
            for (var i = Rules.length - 1; 0 <= i; i--) {
                var cssRule = Rules[i];
                iterator.call(styleSheet, cssRule, i, Rules);
            }
        });
    }
    var deleteRule = function(matchSelector) {
        var skipMatchTest = false;
        // 引数なし or * の場合、全てのruleを削除する
        if (!matchSelector || matchSelector === "*") {
            skipMatchTest = true;
        } else if (typeof matchSelector === "string") {
            matchSelector = new RegExp("^" + matchSelector + "$", "i");
        }
        // iteratorを作りcssRuleごとに処理させる
        var iterator = function(cssRule, idx, sheet) {
            var selectorText = cssRule.selectorText;
            if (!selectorText) { // @importなどは無視
                return;
            }
            var stylesheet = this;
            if (skipMatchTest || matchSelector.test(selectorText)) {
                //console.log(stylesheet, selectorText, cssRule, idx);
                stylesheet.deleteRule(idx);
            }
        }
        forEachRule(iterator);
    }
    return {
        deleteRule : deleteRule
    }
})(ss || {});
ss.deleteRule(/\.[fc]\d+/i);
remove*やdelete*のメソッドを使う機会があんまり無くて、使う度に同じ事にはまってて嫌な気分。
 

2011年6月18日土曜日

アドレスバーからjavascript:を実行できなくするブラウザ側の対策について

Facebookなどで、裏技する方法などと言ってjavascript:をアドレスバーにコピペして実行させて、情報を盗んだりするソーシャルエンジニアリングが流行っていて(ニコニコでも似たようなのありましたね)、それを防止するためにブラウザ側が取っている対策を書き出してみたもの。

IE9の場合

アドレスバーにテキストを貼り付けたときには、javascript: というプレフィックスは削除されます。これは、ソーシャルネットワーク上でよく見られる、ユーザ自身の手によるXSSというソーシャルエンジニアリングなXSS攻撃を軽減します。
IE9 RC マイナーな変更点リスト - 葉っぱ日記

javascript:alert(1);
上記をコピペしたときはalert(1);部分だけがアドレスバーに残るという対策。
手動で、javascript:alert(1);と書いて実行した場合はちゃんと実行できる。
実行コンテキスト(実行した際に影響を与える事ができる場所)も表示している現在のページ(未確認表示しているページがコンテキストになるようです)
 
Chromeの場合

Chromium 13: defenses for self-XSS via javascript URLs Working together with Facebook and other browser vendors, we’re trialing a self-XSS defense that makes it harder for users to shoot themselves in the foot when they are tricked into pasting javascript: URLs into the omnibox.
Chromium Blog: New Chromium security features, June 2011

Chrome13からIE9と同様にコピペした際にjavascript:部分は削除される。
手動でjavascript:alert(1);と書いて実行した場合はちゃんと実行できる。
実行コンテキストも表示している現在のページ。

Firefoxの場合

ロケーションバーへ入力された javascript: と data: URL が、現在表示されているページの権限を継承しなくなりました
アドオンを Firefox 5 と 6 へ対応させるための注意点 « Mozilla Developer Street (modest)

Firefox6からこの変更が適応されている。
IE9やChrome13とは異なるアプローチで、javascript:alert(1);とコピペする際には何も起こらない。
しかし、アドレスバーでjavascript:を実行する際のコンテキストが異なるようになったため、javascript:で実行するスクリプトは表示しているページに影響を与えることができない。(多分DOMが使えないので多くのスクリプトはエラーになる。)

image

実際にFirefox/6.0a2で適当なページを開いてやってみると、windowオブジェクトが存在しないというエラーになった。このようにそのページのDOMにアクセスできないようにする事で、ユーザ自身によるXSSを行えなくしている。

これはアドレスバーから実行するものを無害化するために導入されたので、通常のブックマークレットからの実行やaの埋め込みからの実行などは問題なく動作する。

<a href="javascript:...>HOGE</a>
またjavascript:ハックとか呼んでるコード内でlocation.hrefに入れてJavaScriptを実行させる方法も問題なく動作した。
function evalInPage(fun) {
location.href = "javascript:void (" + fun + ")()";
}
evalInPage(function(){
alert(1)
});

つまり、ロケーションバー以外には特に影響がないという感じらしい。
同じようにdata:スキームURLにも適応される。

ロケーションバーからjavascript:を実行する愛好家達には不便になるかもしれない。(@hasegawayosukeさんとか)

愛好家達の対応策としては

  • それ専用のブックマークレットを作る
  • 多くの場合evalInSandboxからの実行でも動作は異ならないのでxqjsなどのアドオンを使う。
  • Firebugはevalで実行してるのでそれを意識して書く

Firefox6ではScratchpadっていうものが標準でついている。(これはどういう風に実行されてるかは知らない、多分evalInSandboxだと思うけど)

image

など。

おまけ

FirefoxではNoScriptを使う事で、Firefox6未満でも同様の効果を得られます。(この動作だけを得たいという人はほとんどいないと思いますが…)