seezoo v1.1.0をリリースしました!

OSC Nagoyaにseezooの紹介で参加してきました
に関連づいての記事となりますが、8/20にseezooの新バージョン1.1.0をリリースしました。


当初のリリース予定からだいぶ遅れてしまいました・・・。
期待してくださっていた方、ごめんなさい。そして、お待たせしました!

結構沢山の機能を詰め込みました。


もうちょっと細々とやれば良かったんですがね><


ともあれ、ようやっとリリースすることができました。良かった。

追加された機能とか


一番大きな機能は「メンバー管理」です。会員制サイト、またログインして何かやってもらうためのプロトタイプとして使えるよう、かなり柔軟な作りにしました。
実は、もともとはseezooのフォーラム機能で、「ログインしたユーザが書き込みできる」ということを実現するために作り始めたのですが、汎用性を考えるうちに肥大化していきました。

もちろん、「必要に応じて」ということなので、「そんな機能はいらないよ!」という方はアンインストールしたり、ナビゲーションから外したり、アクセス権限をなくしたりしてもらえばOKです。

その他、SSLページが作れるようになったり、ブログ機能が拡充されたりと、色々な所に手を入れました。

詳しくは、ユーザガイドの変更履歴を参考ください。
バグFIXもかなり沢山やりました(^-^;まだこれだけ不安定だったと言うことですね。むむむ。

次の目標とか予定とか


OSCでも要望を頂いたのですが、当面の目標は、「スマフォとガラケーの対応」になると思います。
その他、ブログの機能アップとか、プラグイン機構の準備。この辺りを折を見て盛り込んでいこうと思っています。っていうか、既に開発始めてます。
ご期待頂ければ幸いです。

それから、今度からはもう少しリリース間隔を短くして、細かくバージョンを積み重ねていこうと思います。

お知らせ


OSC Nagoyaのセミナーではお知らせしましたが、近日中に公式サイトにフォーラムを設置する予定です!

今まではTwitterなどで報告を頂いていたのですが、やはり140文字では限界が・・・。あとOSSなプロジェクトにはやはり必須であるので、頑張って実装しました。
開設の際には、ぜひ登録して書き込んで頂けると嬉しいです。みなさんのお力を拝借したいと思います。


おまけ


seezooの里親の会ならぬ、ユーザ会が立ち上がるようなので、勝手にワクワクしてます。
関連の方、ぜひぜひよろしくお願いします!

OSC Nagoyaにseezooの紹介で参加してきました

8/20日オープンソースの文化祭!ということで、seezooも参加してきました。

簡単に感想から言いますと、


ひたすら色んな方々とお話しまくってました。


また、例によって


写真とか撮ってませんでした><


OSC Nagoyaとのご縁


実は、seezooの初リリースの時もこのOSC Nagoyaで発表させていただいた事もあり、今回も新バージョンのリリースに合わせて参加させていただきました。何かと縁を感じずにはいられません。


※リリース記事は後で書きますー。

リリース記事書きました。


毎度のことながら、前日までリリース準備、ブースの準備を必やって、何とか間に合った感じでした。
まぁ、こういうお祭りの準備をするのってやっぱり文化祭の前日みたいで楽しいですよね。
とりあえず、リリースパッケージのDLができるようにして当日へ。


今回はOSSのseezooに加えて、商用パッケージ「seezoo more」の紹介もするので、
ちょっと準備は念入りにやりました。

当日の事


今回は、名古屋国際センターでの開催でした。天気はあいにくの小雨でしたが、それほど強く降ることもなく、外は結構涼しかったんじゃないかと思います。
写真、撮ってないんですがね・・・。


こういう場でないとなかなかお会いできない方々とお話できる機会、また、個人的にお会いしたかった方々ともお会いできたと思います。


セミナーも、実は「申し込み人数少ないので・・・」と事務局の方から連絡を頂いていたのですが、
いざやってみると席はほとんど埋まっていて、またブースに足を運んでくださる方の多さに、
seezooへの興味をひしひしと感じつつ、密かに感激しておりました。
セミナー、ブースに来てくださった皆さん、ありがとうございました。




13:00からでした。


私はセミナーで話したり、色々な方とお話したり、Joruri CMSセミナーを聞きに行ったり、Ustreamに出演させていただいたりと、
一人でバタバタと動き回ってて、あんまりブースにいなかったかもしれません><
ブースで待機して説明してくださってたスタッフの皆さん、ホントありがとうございます。
次はもっとブースに居るようにします、はい。


あと、個人的にKonoha Projectというのがすごく気になったので、後でこっそり使ってみようと思います。
スクリプト言語大好き。


これからの課題と感想を改めて


「seezooは俺が作ったんだぜへっへ〜」などと偉そうにする気は毛頭ないですが、
慢心ではなく、これから使ってくださる方が増えそうな兆し、それからseezooへの期待を僅かながらも感じた一日でした。


同時に、こういうプロジェクトって一人ではとてもできず、色々な方の助けをもらってできてるんだー、と改めて思います。
開発者が偉いんじゃなく、seezooに関わってくれて、力を貸してくれる方々の方がはるかに偉い。
そして、みんなでやるから楽しいんですよね。それって、やっぱりお祭りです。


合わせて、色々な要望も頂きました。実装に至るかは分かりませんが、全部メモに残してあります。
改めて、みなさんが使いやすいものになるようにもっと精進しなければと思ったOSCでした。
やっぱり自分の頭だけで考えててはダメですね。


こういう場に出る度に、勉強させてもらってます。


おそらくですが


来年も出る(出たい)よ!

seezooを使ってみよう会 vol.1を開催しました

やや遅めのエントリーですが、7/30日に記念すべき愛知県で初の勉強会を開催させて頂きました!

seezooをリリースしてからはや2年ですが、実際に使っていただいている方、また興味を持ってくださっている方にお会いできる機会ということで、とても感激な一日でした。
今回は開発元である名古屋での開催、ということで、ちょっと緊張してました。


緊張してたこともあり、写真とか全然撮ってませんでした・・・

予想に反する申し込み者数

会場が約30人くらい入れる所で、「大体20人くらいで募集して、半分くらい来てもらえたらいいですね〜」と話していたのですが、いざ募集を開始すると結構なスピードで席が埋まっていくのには驚きました。
最終的にはほぼ満員となりました。ありがとうございます。実際、20人でも狭かったかもしれませんね・・・。

私自身、それほど積極的に宣伝ができておらず内心ドキドキだったのですが、ほっとしたというか、なんというか、です。
準備していたスライドから考えると時間が余りそうな予想でしたが、いざやってみれば時間ピッタリでした。

seezooへの思いと実際に使ってもらうコンセプト

プログラムとしては、最初に私がseezooのコンセプトやら、設計やら、seezooを使ってぜひやってもらいたいことを色々とお話させていただきました。

「楽しくなければWebじゃない!」とか言ってましたが、正直な所、私自身が楽しんで作ってるものですから、それをみなさんと共有できるのが一番嬉しいことです。
果てはそれがクライアントさんにも伝わるようなモノでありたい、というのが私の思いです。
(所々ネタのような画像を使っててスミマセンデシタ><)


CMSは沢山ありますが、「これに比べてこう」、というのではなく、
クライアントさんの要望に合わせて、使えるCMSの選択肢の一つになればいいなと思います。
もちろん、他のCMSと併用するのもアリです。


後半は実際にインストールして、テンプレートを作ってもらう所までやってもらいましたが、さすが皆さん慣れてらっしゃるのか、テンプレート作成は簡単にされていたようです。
環境を用意するのに少し時間がかかってしまった点は反省点でしょうか。その場でネットワークを立ててくださった方がいたり、参加者の方にも助けられました。
この場を借りて改めてお礼申し上げます。ありがとうございます!

反省点と今後に向けて

準備不足もあり、色々と反省する部分もありましたが、少しでもseezooを知って、使ってみようかなと思ってもらえたかな〜、と個人的には思っています。
反省点は、次回にむけての課題、ということで。


というわけで、明確な時期は決めていませんが、第二回もぜひやりたいなーと思います。
(もうあんまりネタがなかったりしますが・・・)


最後に、月末で忙しい中、準備など手伝ってくださったスタッフの皆さん、そして参加者のみなさん、
ありがとうございました!

・・・次はスタッフさんとか、会を手伝ってくれる方が増えるといいな。

おまけとお知らせ

8/20のOSC名古屋にseezooとして出展します!
それに合わせて、1.1.0の新バージョンのリリースを行います。
今回参加できなかった方、またより詳しく聞いて見たい方は、ぜひ会場に遊びに来てくださいね。

CodeIgniterのダウンロードヘルパで大きめのファイルをダウンロードさせるヘルパを作ってみる

少し問題になるケースがあったので、ヘルパを拡張してみます。

そもそもの発端

動画ファイルなど、比較的サイズの大きいファイルをCodeIgniterのdownload_helperでダウンロードさせようとしたときに、
「メモリ、足りないよ」と怒られたので、何とかしたいな〜ということで作ってみました。

download_helperの挙動と実際の動作

CIのdownload_helperには「force_download」というヘルパ関数があり、引数を渡すだけで簡単にダウンロードしてくれる便利な関数があります。仕様は、

force_download('filename', 'data')

データを強制的にデスクトップにダウンロードさせるためのサーバヘッダを生成します。 ファイルのダウンロードで使えます。 第1引数には、ダウンロードファイルにつけたい名前を指定し、第2引数には、ファイルのデータを指定します。

CodeIgniterユーザガイド日本語版 - ダウンロードヘルパ部分抜粋


ということで、第二引数には実際のファイルのデータ(Binaryも含む)を渡すことで、ヘッダの付加などをやってくれます。

なので、実際のファイルデータをfile_get_contents()などで読み込んでデータを渡すのですが、この時ファイルサイズが著しく大きい、つまりphp.iniのmemory_limitの値より大きいサイズを読み込むと、当然メモリが足りなくてダウンロードできません。

それほど大きなファイルをDLさせるケースを想定していない、ということなのでしょうが、seezooでは動画ファイルとかも扱ったりするので、これだとエラーが出てDLできませんでした。困りました。

考えた方法と対策した関数を拡張して実装する

対策は簡単で、


DLを始める前に、そのファイルのサイズを調べてから、memory_limitより大きい場合はsplitしながらダウンロードさせればいい


のですが、結構手間がかかるので、もう一つ関数を追加します。以下、関数のコードです。
MY_download_helper.phpとか作るといいかもです。


/**
* ファイルサイズを調べてから、ダウンロードをさせる関数
*/
if ( ! function_exists('split_force_download'))
{
function split_force_download($filename = '', $filepath = '')
{
// same codeigniter code:
if ($filename == '' OR $filepath == '')
{
return FALSE;
}

// Try to determine if the filename includes a file extension.
// We need it in order to set the MIME type
if (FALSE === strpos($filename, '.'))
{
return FALSE;
}

// Grab the file extension
$x = explode('.', $filename);
$extension = end($x);

// get PHP memory_limit
$ini_max = trim(ini_get('memory_limit'));
switch ( strtolower($ini_max[strlen($ini_max)-1]) )
{
case 'g':
$max_size = intval($ini_max * 1024 * 1024 * 1024);
break;
case 'm':
$max_size = intval($ini_max * 1024 * 1024);
break;
case 'k':
$max_size = intval($ini_max * 1024);
break;
default :
$max_size = intval($ini_max);
}
$file_size = filesize($filepath);

// Load the mime types
@include(APPPATH.'config/mimes'.EXT);

// Set a default mime if we can't find it
if ( ! isset($mimes[$extension]))
{
$mime = 'application/octet-stream';
}
else
{
$mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
}

// Generate the server headers
if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE"))
{
// Internet Explorer filename should be SHIFT_JIS encoded filename.
$filename = mb_convert_encoding($filename, 'SHIFT_JIS', 'UTF-8');

header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".$file_size);
}
else
{
header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
header("Content-Length: ".$file_size);
}

// if filesize greater than max_memory_limit, split download
if ($ini_max > 0 && $max_size < $file_size)
{
flush();
$fp = fopen($filepath, 'rb');
while(!feof($fp))
{
echo fread($fp, 4096);
flush();
}
fclose($fp);
exit();
}
else
{
exit(file_get_contents($filepath));
}

}
}


作った、と言っても既存のforce_download()を少しいじっただけのものですが・・・。
関数名にいつも悩むのですが、「split_force_download」にしました。青の部分が追記している部分です。
黒字の部分はforce_downloadを流用しています(同じ処理)。

コードについてなど

まず赤字の部分、関数の第二引数には読み込んだデータではなく、DLさせたいファイルへのパスを渡します。重要です。
その後、対象ファイルのサイズと、現在動作している環境のmemory_limitのサイズを比較して、大きければflush()→fread()の繰り返しで分割しながらダウンロードを継続させます。
それ以外の場合は通常どおり、ファイルを読み込んでダウンロードします。

あと、IEでforce_downloadに通すと日本語のファイル名が文字化けすることがあったので、SHIFT_JISに変換してダウンロードさせるようにもしていますね。

分割しているからと言って負荷が軽くなっているわけではないと思います。そもそもmemory_limitの値を大きくすればいい話なのですが、
それを変更できない環境もあるかもしれないので・・・ということで。

感想とか

ファイルアップロードの時点では、upload_max_filesizeの設定値が使われますが、

memory_limit < upload_max_filesize

のケースでもアップロードは成功するんですねー(ファイルの中身は見ないですもんね)。
よくよく考えると生データを引数に受けてDLというのはどうなのかな?とも思ったりしましたが、あまり気にしないことにしました。

ファイル共有アプリとかでは使える関数かもしれないですね。seezooでも動画ファイルのDLにはこちらの関数を使ってDLさせています。
Zip圧縮クラスを併用すると幸せになれそうですね^^

w3afでアプリケーション脆弱性診断してみる

「w3af」というツールの1.0がリリースされたらしいので、早速試してみました。

w3afとは、


w3afは、Webアプリケーションの攻撃および監査フレームワークです。w3afのコア部分やプラグインPythonで実装されています。SQLインジェクションのチェックやクロスサイトスクリプティングXSS)、ローカル/リモートファイルインクルージョンなどを含めた130以上のプラグインが提供されています。

w3af プロジェクト日本語トップページ - SourceForge.JP

ということらしいです。ふむふむ。英語わかんないですが、試してみましょう。

ダウンロードとインストール

公式サイトのダウンロードページにbz2のパッケージがあるのでダウンロード。Windows用にバイナリのパッケージもあるみたいですよ。

パッケージを展開すると、「w3af_console」と「w3af_gui」があります。せっかくだから、GUIツールの方でやってみます。
環境は、Ubuntu10.04です。

とりあえず実行権限をつけて起動すると、色々パッケージが足りないと言われたので、その通りにインストール。



$ sudo apt-get install nltk SOAPpy libxml2 pysvn scapy


再度起動すると、



You have to install graphviz library.


ライブラリが足りないみたいです。インストール。



$ sudo apt-get install graphviz


再度起動すると、スプラッシュが出ました。



テストしてみる

続いて、GUIウインドウが出てきたので、左上のボタンからウィザードに従って入力。
今回はshort wizard、ローカルにあるLAMPP環境でテストしてみます。




といっても、URLとOS、検証する言語を選択、最後にプロファイル名を入れれば準備完了。




あとはチェック項目をONにしてとりあえず、Run。
どれがどの項目なのか分からないので、「audit」、「grep」、「mangle」あたりにチェックを入れました。
(discovery)にチェックを入れると、「すっごい時間かかるかもよ!」というダイアログが出たのでやめました)

お試し用のスクリプトはこんな感じ。



  
  
  
  <div>
    <?php echo @$_GET['id'];?>
  </div>
  


良い子は真似しちゃダメなコードです。

で、スタートすると、結果や情報がログにダーッと出て、終了後に「Results」のタブから結果が確認できます。
簡単なスクリプトならいいですが、それなりなアプリケーションを検証すると、かなりマシンパワーを使う感じです。
あと、エラーが出ちゃう場合はそこで止まってくれるので、エラー検出にも使えそうな印象です。

結果を見ると、あれ、、、XSS脆弱性の指摘がされないですね。オプションのチェック項目が悪いのかもしれませんね。
でもちゃんとDirectoryIndexできちゃうよ、とかの警告はしてくれました。
あとxstの警告が出まくったので、設定を修正したりしました><

実際にリクエストするコードを吐き出せる

w3afの面白い所は、まずい箇所があったときに実際にリクエストを送るコードをhtml, Ruby, Pythonなどのいろんなフォーマットで吐き出せる所だと思います。
それを保存して、実際にリクエストを送ったりできますし、w3af上でリクエストヘッダを変えながら検証したりできるみたいです。

感想

もうちょっと使い込んでみたいと思います。あと英語も勉強しないといけないですね。
seezooで試したら30分くらいガリガリ回って、エラーはありませんでした。オプションの設定次第かもしれませんが・・・。

CodeIgniter用スマートフォン判定ライブラリを作ってみた

CI2.x系の話題が活発な中、未だに1.7.3でコソコソやってる私です。
seezooもそのうち2系で動かしたいのですがね。

発端

「そろそろスマートフォンくらいは対応した方がいいかもね」という訳で、とりあえずアクセスしてきたユーザーのキャリアくらいは判定したいので、ライブラリを書いてみました。

やってることとコードとか

ガラケーのようにIPが云々とかそういうのがないので、単純にUser-Agentの文字列を見て判定するだけのものです。これだけだとライブラリである必要もないと思うので、キャリア名とOSのバージョンも取得するようにしてライブラリの体裁を整えたりしてます><

あ、Windows Mobileとかe-mobileの判定はできません。すいません。


以下、コードです。クラス名で悩みましたが、mobileipに習って「mobilesp」にしてみたり。ちょっと長いです。

_detect_sp();
}

// public methods ----------------------------------

/**
* get Accessed User-Agent
* @access public
* @return string
*/
public function get_agent()
{
return $this->_agent;
}

/**
* Access Agent is Smartphone carrier?
* @access public
* @return bool
*/
public function is_smartphone()
{
return $this->_is_sp;
}

/**
* get carrier OS name
* @access public
* @return string $OS
*/
public function os()
{
return $this->_sp_os;
}

/**
* get OS version
* @access public
* @retrurn float $os_version;
*/
public function version()
{
return $this->_os_version;
}

// version compare
public function version_compare($v, $cp = FALSE)
{
if ( $cp )
{
return version_compare($this->_os_version, $v, $cp);
}
else
{
return (version_compare($this->_os_version, $v));
}
}

// private methods ======================================================

/**
* _detect_sp
* SmartPhone carrier detection from User-Agent
* @access private
* @return void
*/
private function _detect_sp()
{
// get User-Agent
$ua = $this->_agent = (isset($_SERVER['HTTP_USER_AGENT']))
? $_SERVER['HTTP_USER_AGENT']
: FALSE;

if ( ! $ua )
{
return;
}

// detect sp
foreach ( $this->_sp_agents as $agent )
{
if ( strpos($ua, $agent) !== FALSE )
{
$this->_is_sp = TRUE;
$this->_sp_os = $agent;
// set carrier flag
$this->{'_is_' . strtolower($agent)} = TRUE;
break;
}
}

// If Smartphone access, detect OS version
if ( $this->_is_sp === TRUE )
{
$this->_detect_os_version();
}
}

/**
* Detect carrier OS version
* @access private
* @return void
*/
private function _detect_os_version()
{
if ( $this->is_android === TRUE )
{
$version = preg_replace('|(?:.+)Android ([0-9]+)\.([0-9]+)(?:.+)|', '$1.$2', $this->_agent);
}
else
{
switch ( $this->_sp_os )
{
case 'iPad':
$prefix = 'CPU';
break;
default:
$prefix = 'iPhone';
break;
}
$regex = '|(?:.+)' . $prefix . ' OS ([0-9]+)_([0-9]+)(?:.+)|';
$version = preg_replace($regex, '$1.$2', $this->_agent);
}

$this->_os_version = floatval($version);
}
}

やってる事は、

  1. User-Agentの値を取得
  2. 特定のスマートフォンの文字列があるかどうか判定
  3. あればOSのバージョンも取得(minorまで)

という感じです。未検証ですが、iOS2.x位からは取得できると思います。
(細かいUA文字列が分かりませんでした)


$this->{'_is_' . strtolower($agent)} = TRUE;とかキモチワルイですかね・・・。


あと、publicにis_androidなどのフラグを参照できるような簡単な形式なので、ちゃんとprivateにしてgetterを作った方がいいかもしれないです。

使い方とか

いつもどおりです。system/application/libraries/以下に配置して、


$this->load->library('mobilesp');
if ( $this->mobilesp->is_smartphone() === TRUE )
{
// スマフォ用の処理
if ( $this->mobilesp->is_android === TRUE )
{
// Android用の処理
if ( $this->mobilesp->version() > 1.6 )
{
// Android 1.6+用の処理
}
}
}

という感じで細かい制御ができますかね。
パパッと書いたものなので、ご自由にお使いください(責任は取れませんが><)
CI2.x系でも動くハズです。

感想

JavaScriptでもユーザーエージェントの判定はよくやりますが、いよいよキャリアが増えてきて手間がかかるようになりましたね・・・。
OSのバージョンを取るときに、iPhoneだと「iPhone OS 3_2_...」なのにiPadだと「CPU OS 3_2_...」となるのがちょっとよく分かりません。
もっと厳密な検出方法があればぜひ教えてください。

大名古屋JS #daiNagoyaJS を開催しました


去る2011/04/17の日曜日に、「大名古屋JS」なる集まりを開催しました。
名古屋名物エアリプライを飛ばしながら、僕が言い出しっぺ、さらに何をやるかも決まってないにも関わらず
@ahomu、@kiyotchi、@ritaw、@issmさんというメンバーが集まってくださいました。

@issmさん、@riatwさんは前日に #mtddcがあったにも関わらず参加して頂きました(会場も同じでしたすいません)。
個人的には、@ahomuさんとはお会いしたかったのでいい機会でしたー。


僕以外みんなMacだったけど泣かずにがんばりました。

話したこととか

「JS」という名目ではありますが、SQLCMS、さらには業務のお話など、カテゴリは様々。
普段あまり外で話す機会のない私としては、すべてが興味深くて新鮮でした。
(特に他の会社さんがどんな感じでやってるのか、とか・・・)

node.js

私もこんなネタを準備していったわけですが、@ahomuさんがすでにアプリを作ってたり、みなさんがその場でインストールして動かしてたり、さすがでした。ベースがJavaScriptなので、比較的抵抗ないですよね。
ちょっとしたアプリケーションに使えたり、サーバーを自分で書いたりするのはやっぱり楽しいです。

CMSな話

かの有名なa-blog cmsデベロッパー@ahomuさん、seezoo作ってる私、MT勉強会主催者な@riatwさん、と愛知県のCMS集団みたいな集まりな感じでした。名古屋のCMSは熱いね!

中でもCMSのテンプレートについて談義できたのは良かったです。「PHP直書きが(表示速度的な意味で)一番速いじゃん!」と思ってたわけですが、
専用タグの方が違和感が無い、という意見や、テンプレート中に<?php」なタグは無い方がいいかも、という意見は参考になりました。
(実は当初のseezooはテンプレートエンジンを載せる予定だったんですよね・・・)

SQLな話

私はSQLが苦手で、社内のエンジニアにお願いする事が多いですが、これを機に勉強しようと思います。
SQLの勉強会もやりましょう!

次どうするの?

やることを決めずに開催したものの、話題ははずみ、約5時間ほどわいわいと話続けました。
最後にソースコードリーディングの話になり、こちらもかの有名なJSライブラリ「uupaa.js」の中をチラ見。
魔法のようなコードの中から学べることは多いと思い、次はuupaa.jsを読んでみようかという方向で開催できそうです。
次はatendとか立ててもいいかもですね。

まとめ

普段は外に出ない(勉強会参加的な意味で)私としては、自分の中でのインプットと、外の方々のインプットのすり合わせができたように思います。
ECプログラマな方、CMS関連の方、マークアップエンジニアな方、オールラウンダー(?)な方と、見事にカテゴリの違うメンバーが集まると、
こうも面白いものかと思い、次も是非やりたいなと思った次第です。

おまけ

終了後に@issmさんと魚民で飲みと語りで3時間ほど。
ありがとうございました><