iPhone用のスタティックライブラリを統合

頻繁にやる作業ではないからかいつも忘れてしまうのでメモ。

iPhoneで外部ライブラリを使う場合、シミュレータ用とデバイス用と2種類用意しないといけないのですが、lipoコマンドを使って両方に対応したライブラリを用意します。

下記が使用方法です。

lipo -create \
    foo/Build/Debug-iphonesimulator/libBar.a \
    foo/Build/Release-iphoneos/libBar.a \
    -output \
    foo/lib/libBar.a

Titanium Developer で シミュレータが起動しない場合の対処方法

昨年秋に はてな技術勉強会 #2を見ながら試して以来触っていなかったのですが、先日の #stidev@masuidriveさんのお話を聞いて俄然興味が出てきたので、今更ながらTitanium Mobileを試してます。

で、いきなりハマった事があるので纏めておきます。

久々にTitanium Developerを立ち上げたら、「新しいSDKがあるよ」的なメッセージが出たので当然インストールした(つもり)。

で、その後新規でプロジェクトを作ったところ、Launchボタンを押してもシミュレータが起動しません...。

何だろうと思いつつ、Titanium SDKのバージョンを下げても似た様な状況...。

buildディレクトリをあさっていると "build/iphone/build/build.log" なんて怪しいファイルを見つけたので見てみると "libTiCore.a" が見つかりませんとのエラーが...。

調べてみると 確かに '/Library/Application Support/Titanium/mobilesdk/osx/1.5.1/iphone/libTiCore.a' が存在しません。1.4.2のディレクトリと比べてもなんだかファイル数も少なかったです。

リビルドとか出来ないのかなぁとかいろいろ調べてみましたが見つかりません。数日放置してたのですが、どうしても色々試したい!

仕方が無いので、'/Library/Application Support/Titanium/mobilesdk/osx/1.5.1' をまるっと移動して Titanium Developerを起動し直したところ「新しいSDKがあるよ」表示が!!!

という事で、あっさり使える様になりました(^^;。
原因は良くわかりませんが、インストールが正常に完了していなかった様です。

Datasourceを使い倒す

CakePHP Advent Calendar2010 も折り返し点を過ぎました。CakePHP Advent Calendar2010は、ネタの調整などはしていないのですが(してないよね(^^;?)、参考になる話ばかりだし、まだネタがかぶったという話は聞かないので正に「君の当たり前に僕らは感嘆させられるんだ」ですね(^^;。

では、13日目の担当と言う事で...。

*この記事の内容はCakePHP1.3での話になります。


CakePHP1.2までは、Datasourceは app/models/datasources/ 以下に配置しないと動作させることが出来ませんでしたが、CakePHP1.3からはプラグイン配下のDatasouceを使用することが可能になりました。
これは個人的にとても嬉しい修正だったのですが、このあたりの情報をWeb上にあまり見かけないのでまとめてみました。

CakePHP Datasources

CakePHPのCoreに含まれていないデータソースは、PHP Matsuriにも来ていただいた Graham Weldonさんが以下でまとめられています。

ここには、以下の様なデーターソースがまとめられています。

  • Amazon Associates Datasource
  • Array Datasource
  • CSV Datasource
  • SORP Datasource
  • XML-RPC Datasource
  • ADODB Datasource
  • DB2 Datasource
  • Firebird Datasource
  • MySQL Log Datasource
  • ODBC Datasource
  • SQLite3 Datasource
  • SQLServer Datasource
  • Sybase Datasource

他には、CakePHP Advent Carendar2010の一日目を担当されたid:cakephperさん作の MondoDB Datasource なんかも最近はホットなのではないでしょうか?
# 弊社でも使わせていただいております!

Datasourceの使い方(準備編)

使用する為に機能拡張等のインストールが全く必要ない、CSV Datasourceを例に実際にDatasourceを使う方法を解説してみたいと思います。

まずは、pluginsディレクトリに CakePHP Datasources を配置します。

 cd APP/plugins/
 git clone https://github.com/cakephp/datasources.git


実際のプロジェクトで利用する場合は、 6日目に@tfmagicianさんが紹介されているように git submoduleを使って管理すると良いと思います。


次に、cvsファイルを配置します。今回は APP/tmp/databases/ に下記のファイルを配置します。

  • APP/tmp/databases/advent_calendars.csv
id,target_date,name,url
1,"2010/12/01","cakephper","http://d.hatena.ne.jp/cakephper/20101201/1291166566"
2,"2010/12/02","k1LoW","http://d.hatena.ne.jp/k1LoW/20101202/1291262612"
3,"2010/12/03","shin1x1","http://www.1x1.jp/blog/2010/12/thinking_abount_cakephp_mode.html"
4,"2010/12/04","remore","http://rimuru.lunanet.gr.jp/notes/post/2838/"
5,"2010/12/05","uechoco","http://labs.uechoco.com/blog/2010/12/cakephp-model-lovers.html"
6,"2010/12/06","tfmagician","http://1-byte.jp/2010/12/06/cakephp_with_git/"
7,"2010/12/07","MASA-P","http://blog.ecworks.jp/archives/1323"
8,"2010/12/08","kanonji","http://d.hatena.ne.jp/kanonji/20101208/1291819950"
9,"2010/12/09","lxcy","http://d.hatena.ne.jp/ixcy/20101209/p1"
10,"2010/12/10","mon-sat","http://text.tklabo.net/blog/26/cakephp-environment-tips"
11,"2010/12/11","msng","http://www.msng.info/archives/2010/12/cakephp-error-only-when-debug-level-is-0.php"
12,"2010/12/12","ogaaaan","http://torhamzedd.blogspot.com/2010/12/cakephp-advent-calendar-12st.html"
13,"2010/12/13","kaz29","http://d.hatena.ne.jp/kaz_29/20101213/1292209088"
14,"2010/12/14","camelmasa","-"
15,"2010/12/15","hiromi","-"
16,"2010/12/16","aerith","-"
17,"2010/12/17","nojimage","-"
18,"2010/12/18","halt","-"
19,"2010/12/19","kunit","-"
20,"2010/12/20","connvoi_tyou","-"
21,"2010/12/21","yashio","-"
22,"2010/12/22","knj77","-"
23,"2010/12/23","osakanapower","-"
24,"2010/12/24","akiyan","-"


最後に、database.phpの設定です。今回datasourceはplugins以下に配置しているので下記の様に定義します。

<?php
define('CSV_PATH', TMP.'databases'.DS);

class DATABASE_CONFIG {
    var $csv = array(
        'driver' => 'Datasources.CsvSource',
        'path' => CSV_PATH,
        'readonly' => true,
        'extension' => 'csv',
        'recursive' => false,
    );

	...
}


これで、準備は完了です。

Datasourceの使い方(使用編)

実際に使用するには、通常のdatasourseを使用する場合とあまり変りないのですが以下のようになります。

  • モデル APP/models/advent_calendar.php
<?php
class AdventCalendar extends AppModel {
    public $useDbConfig='csv';
}
  • コントローラ APP/controllers/advent_calendar_controller.php
<?php
class AdventCalendarController extends AppController {
	public $name = 'AdventCalendar';
  public $helpers = array('Html','Paginator') ;
	public function index() {
	  $results = $this->paginate();
    $this->set(compact('results'));
  }
}
  • ビュー APP/views/advent_calendar/index.ctp
<div class="advent calendar index">
<h2><?php __('Advent Calendar');?></h2>

<p>
<?php
echo $this->Paginator->counter(array(
'format' => __('Page %page% of %pages%, showing %current% records out of %count% total, starting on record %start%, ending on %end%', true)
));
?>	</p>

<div class="paging">
	<?php echo $this->Paginator->prev('<< ' . __('previous', true), array(), null, array('class'=>'disabled'));?>
 | 	<?php echo $this->Paginator->numbers();?>
|
	<?php echo $this->Paginator->next(__('next', true) . ' >>', array(), null, array('class' => 'disabled'));?>
</div>

<table cellpadding="0" cellspacing="0">
<tr>
			<th><?php echo $result['AdventCalendar']['id'];?></th>
			<th><?php echo $result['AdventCalendar']['target_date'];?></th>
			<th><?php echo $result['AdventCalendar']['name'];?></th>
</tr>

<?php
$i = 0;
foreach ($results as $result):
	$class = null;
	if ($i++ % 2 == 0) {
		$class = ' class="altrow"';
	}
?>
	<tr<?php echo $class;?>>
		<td>
			<?php echo $result['AdventCalendar']['id']; ?>
		</td>
		<td>
			<?php echo $result['AdventCalendar']['target_date']; ?>
		</td>
		<td>
			<?php 
				if (!empty($result['AdventCalendar']['url']) && $result['AdventCalendar']['url'] !== '-' ):
					echo $this->Html->link($result['AdventCalendar']['name'], $result['AdventCalendar']['url']);
				else:
					echo $result['AdventCalendar']['name'];
				endif;
			?>
		</td>
	</tr>
<?php endforeach; ?>
</table>


Datasourceの実装によっては通常のRDB用 Datasourceと同じように使えない場合もありますが、基本的な機能は普段CakePHPを使っているのと同じように利用することができます。

参考のために、CSV Datasource以外のDatasourceを使う場合の database.phpの表記サンプルを下記に書いておきます。

<?php
define('TEST_SQLITE_FILE', TMP.'databases'.DS.'test.sqlite3');
...
    // SQLite3
    public $sqlite3 = array(
        'driver' => 'Datasources.DboSqlite3',
        'database' => TEST_SQLITE_FILE,
    );
...
    // mongoDB
    public $default_mongo = array(
        'driver' => 'mongodb.mongodbSource',
        'database' => 'mongotest',
        'host' => 'localhost',
        'port' => 27017,
        /* optional auth fields
        'login' => 'mongo', 
        'password' => 'awesomeness',    
        */
    );  	
...

まとめ

如何でしたでしょうか?今後はRDB以外のDatasourceを扱う機会も出てくると思いますので参考になれば嬉しいです。
また、Datasourceをアプリケーションと切り離すことができますので、Datasourceを作成する場合はpluginとして実装するのが良いと思います。そして、可能なのであればgithubなどで公開してみると面白いのではないかと思います。

明日は、@camelmasaさんです。よろしくお願いします〜。

PHPMatsuriは熱かった!

f:id:kaz_29:20101015000420j:image


大分たってしまいましたが、今回も昨年と同じく、スタッフとして参加したPHPMatsuriがなんとか無事終了しました。ブログを書かないとPHP Matsuriが終わらないので(^^; 私のみたPHP Matsuriについて少し書きたいと思います。

準備

f:id:kaz_29:20101002093601j:image

当日 @yando さんも話していましたが、@yandoさんがNY在住になったという事で当日までスタッフがオフラインで集まる事が一度も無くやり取りはほぼMLとSkypeでのやり取りでした。PHP Matruri HonbuのML投稿数を数えてみると... なんと約980通!Honbuが出来る前に、別のMLでも検討を進めていたので軽く1,000通を超えるメールのやり取りがありました。

今回私は、一部スポンサー様対応やノベリティ関連の発注などを担当していました。なれていない事もあっていろいろとばたばたな部分はありましたがなんとか無事イベントを終える事が出来ました。

セッション

当日はスタッフだった事もありセッションはあまりしっかり聞けていないのですが、 id:hyoshiok さんのおっしゃっていた「達人を見つけて、学ぶ方法を学ぶ(learn how to learn)」はかなり刺さりました。私も若い頃沢山の「達人」たちにいろいろな事を教わりましたし、今もPHP Matsuriの様なイベントに参加して沢山の「達人」たちからいろんな物をもらっています。まだこういったイベントや勉強会などに参加した事が無い人も、参加してみると良いと思いますよ!

ハック!

f:id:kaz_29:20101002205231j:image


事前に「何かサービスを作りたいなぁ。。。」と漠然と考えていたのですが、PHP Matsuri自体の準備や仕事に追われてほとんど自分のハックの準備に時間を取れませんでした。

で、方針を変更して前々から興味があったLithiumでなにか出来ないかコードを眺めつつ考えていたら、MySQLのアダプタはあるのに私の大好きなPostgreSQLのドライバが無いではありませんか!これだ!と思い、当日のハックの内容は決まりました。が、当日の朝まで全く準備はできませんでした。

ハックタイムでは、Lithiumのコードを眺めつつ、環境構築です。MySQL/PostgreSQL両方のテストを動かす為にPHP 5.3.xでMySQL/PostgreSQL両方が動く環境を作っていました。MySQLのテストが動く様にいろいろと設定をしていたのですが、まさかのFatalエラー。根は深そうです...。結局Fatalが出るテストケースはあきらめそれ以外のテストがPostgreSQLでも通る様にと作業を進めました。ただ、実際にアプリとして動作するかというとまだまだいろいろと手を入れないといけない状態でした。こんな状況だったので、午後の発表にエントリーするか最後まで悩みました。が、まぁ折角のイベントですし、後で後悔するのも嫌なので、締め切り5分前にエントリーをすませました。

そしてコンテストの結果はなんと...「Lithium賞 大賞」!
f:id:kaz_29:20101004072443j:image


投票くださった皆様本当にありがとうございました!めちゃめちゃうれしかったです。

PostgreSQLアダプタはまだ未完成なので、今後も時間を作って開発を続けたいと思っています!

英語

そしてやはり今年も英語はだめだめでした(;_;。来年(?)に向けて精進します!

まとめ

f:id:kaz_29:20101004121254j:image


今までに無い形式のイベントなのでいろいろと不安もありましたが、想像していた以上に盛り上がり、私自信もとても楽しかったです!参加してくださった皆さん、ありがとうございました。

本当にもう個人で開催できる規模ではない(^^; ので、来年のことは全く分かりませんが、また機会があればみんなでハックしましょう!

最後に、@yandoさん、id:cakephperさん、@sizuhikoさんはじめスタッフの皆さん!本当におつかれさまでした!

ssh接続で 'Too many authentication failures'

久々の更新です。ちょっと焦ったことがあったのでメモ。

サーバーを移転中で、今日ベンダーさんから設置完了の連絡があり ssh で接続しようとした所こんなエラーが...

Received disconnect from XXX.XXX.XXX.XXX: 2: Too many authentication failures for hoge

なんか怪しいエラーです(^^;

今回のサーバーは、sshVPN経由のみの接続ということで passwd認証ありで構築されている様子。
ヘルプを見ると -o で色々とオプションを指定できるということでこんな感じ。

$ ssh -2 -o PreferredAuthentications=password hoge@XXX.XXX.XXX.XXX

無事接続できました!

最近は、Objective-Cと戯れる毎日です。来月くらいには、iPhoneアプリを公開できるとおもいます。
無事公開したら報告したいと思います〜。

openssl-1.0.0 + mod_ssl-2.8.31

ずいぶん昔に制作したサーバーの移転準備をしています。
openssl-1.0.0がでていたので使おうとしたら、apacheのコンパイル時に以下の様なエラーがでました。

gcc -c -I../../os/unix -I../../include -DLINUX=22 -DHAVE_SET_DUMPABLE -I/usr/include/gdbm -DMOD_SSL=208131 -DUSE_HSREGEX -DEAPI -DUSE_EXPAT -I../../lib/expat-lite `../../apaci` -fpic -DSHARED_MODULE -DSSL_COMPAT -DSSL_USE_SDBM -I/usr/local/include -DMOD_SSL_VERSION=\"2.8.31\" ssl_util_ssl.c && mv ssl_util_ssl.o ssl_util_ssl.lo
ssl_util_ssl.c: In function ‘SSL_X509_isSGC’:
ssl_util_ssl.c:327: error: ‘STACK’ undeclared (first use in this function)
ssl_util_ssl.c:327: error: (Each undeclared identifier is reported only once
ssl_util_ssl.c:327: error: for each function it appears in.)
ssl_util_ssl.c:327: error: ‘sk’ undeclared (first use in this function)
ssl_util_ssl.c:336: error: expected expression before ‘)’ token
make[4]: *** [ssl_util_ssl.lo] エラー 1
make[3]: *** [all] エラー 1
make[2]: *** [subdirs] エラー 1
make[2]: ディレクトリ `/usr/local/src/apache_1.3.41/src' から出ます
make[1]: *** [build-std] エラー 2
make[1]: ディレクトリ `/usr/local/src/apache_1.3.41' から出ます
make: *** [build] エラー 2

調べてみたところ、openssl-1.0.0で、STACK構造体が _STACK に変更になった様です。

// openssl-0.9.8n/include/openssl/stack.h 66-74
typedef struct stack_st
        {
        int num;
        char **data;
        int sorted;

        int num_alloc;
        int (*comp)(const char * const *, const char * const *);
        } STACK;

// openssl-1.0.0/include/openssl/stack.h 66-74
typedef struct stack_st
        {
        int num;
        char **data; 
        int sorted; 

        int num_alloc;
        int (*comp)(const void *, const void *);
        } _STACK;  /* Use STACK_OF(...) instead */

構造的な変更は無い様なので、mod_sslに以下の様なpatchをあてて対応しました。

--- ssl_util_ssl.orig.c 2010-04-17 13:11:24.000000000 +0900
+++ ssl_util_ssl.c      2010-04-17 13:12:05.000000000 +0900
@@ -324,7 +324,7 @@
 {
     X509_EXTENSION *ext;
     int ext_nid;
-    STACK *sk;
+    _STACK *sk;
     BOOL is_sgc;
     int idx;
     int i;
@@ -333,7 +333,7 @@
     idx = X509_get_ext_by_NID(cert, NID_ext_key_usage, -1);
     if (idx >= 0) {
         ext = X509_get_ext(cert, idx);
-        if ((sk = (STACK *)X509V3_EXT_d2i(ext)) != NULL) {
+        if ((sk = (_STACK *)X509V3_EXT_d2i(ext)) != NULL) {
             for (i = 0; i < sk_num(sk); i++) {
                 ext_nid = OBJ_obj2nid((ASN1_OBJECT *)sk_value(sk, i));
                 if (ext_nid == NID_ms_sgc || ext_nid == NID_ns_sgc) {

2010.5.20 追記
http://dsas.blog.klab.org/archives/51719714.html
こんな情報もあるようなので、1.0.0の使用は注意が必要な感じですね。

2010.5.20 追記2
http://slashdot.jp/security/comments.pl?sid=490412&cid=1742785
makeのオプションにOPTIM=-DSTACK=_STACKを指定するとソースは修正せずに対応できるようです。

独自namedパラメータを使って逆ルーティング

結構な忙しさなのですが、id:cakephperさんのTweetをみて妙に納得してしまったので、昨日はまってた事をまとめました。

CakePHP 1.2.5で開発中です。

namedパラメータはなかなかに便利なのですが、独自のnamedパラメータを使っているURLの逆ルーティングではまったのでちょっと調べてみました。

通常の以下の様なルーティングであれば、独自のnamedパラメータも問題なく使えます。

<?php
Router::connect('/:controller/:action/*');

$url = Router::url(array('controller' => 'posts', 'action' => 'index', 'mode' => 'test')) ;
// 正しく変換できます
// $url = "/posts/index/mode:test"

ところがprefix routingを使ったりすると状況が変わります。例えば、以下の様に携帯対応のためにprefix routingとURLにセッションキーを埋め込むような場合ですね。

<?php
Router::connect('/m/:session/:controller/:action/*', 
  array('prefix' => 'mobile', 'mobile' => true), 
  array('session' => '[a-zA-Z0-9]{32}')
);

$url = Router::url(array('controller' => 'posts', 'action' => 'index', 
  'mobile' => true, 'page' => 1, 'session' => '11111111112222222222333333333344')) ;
// page等のCakePHPで標準的に使われているnamedパラメータは問題なし
// $url = "/m/11111111112222222222333333333344/posts/view/page:1"

$url = Router::url(array('controller' => 'posts', 'action' => 'index', 
  'mobile' => true, 'mode' => 'test', 'session' => '11111111112222222222333333333344')) ;
// 独自のnamedパラメータを使うとこんな感じになってしまいます
// $url = "/posts/view/mobile:1/mode:test/session:11111111112222222222333333333344"

色々と調べた結果、namedパラメータとして使用する変数名を登録することができるようです。

Routerクラスに定義されている、connectNamedを使うことで使用可能なnamedパラメータをカスタマイズすることができます。
例えば上記の例の場合には、以下のように指定すると正常に変換できるようになります。

<?php
// 'default'=>true を指定しないとCakePHP標準のnamedパラメータを上書きしてしまうので注意!
Router::connectNamed(array('mode'), array('default'=>true)) ;

connectNamedメソッドのコメントを見ると適用するコントローラやアクションを指定出来そうなのですが、私が試した範囲では制限をかけられませんでした。(アプリすべてのコントローラに適用されます)
追いかけきれていないので、時間ができたらもう少し調べてみたいと思います。

参考

  • ルーティングの設定に失敗するとハマる事がおおいので、しっかりテストも書きましょう!ということで、ルーティングのテストについては以下の新原さんの記事がとても参考になります!