ホーム ブログ ページ 47

10分ではじめるウェブサービス

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。


よしだです。

今回は無料で使える PaaS「Heroku」を利用して、簡単にウェブサービスを作成、公開する方法を紹介します。

 概要

Heroku」は無料で使える PaaS です。

PaaS とは IaaS (一般的なVPS)をベースにしたもので、実用に不可欠であるウェブサーバや DBMS などを最初から備えているサービスを指します。PaaS を利用すれば「ちょっとしたウェブサービスを作って公開したい!」といったときに、自らサーバ構築を行う必要がなくなります。とくに「Heroku」は無料で利用することができ、さらに「サービスの人気向上に伴うサーバ強化」などのスケーリングが必要になった際にも、課金サービスを受けることで柔軟な対応が可能になります。

今回はこの「Heroku」の利用方法を紹介します。

 1. Heroku に登録

1. メールアドレスの登録

まずは Heroku のアカウント登録ページでメールアドレスを入力します。

https://api.heroku.com/signup

メールアドレスを登録すると下記の画面に遷移します。

https://api.heroku.com/signup/ok

2. メールの確認

Heroku から届いたメールを確認し、記載されている URL にアクセスします。

「Welcome to Heroku」と書かれた入力フォームが開かれます。

3. パスワードを設定

適当なパスワードを設定し、「Save」ボタンを押します。

Heroku への登録はこれだけでおしまいです。

次にクライアント側のセットアップに移ります。

 Heoku に必要なソフトウェアをセットアップ

1. git 、ruby、rubygems をインストール

今回はウェブサービスの作成に Ruby on Rails を使用することにします。

Heroku では Rails3 がサポートされているので、これに対応するソフトウェアをインストールします。

CentOS の場合:

# yum -y install git
# wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.gz
# tar xvzf ruby-1.9.2-p290.tar.gz
# cd ruby-1.9.2-p290.tar.gz
# ./configure
# make
# make install
# cd
# wget http://rubyforge.org/frs/download.php/74619/rubygems-1.7.2.tgz
# tar xvzf rubygems-1.7.2.tgz
# cd rubygems-1.7.2
# ruby setup.rb
FreeBSD の場合:

# echo 'RUBY_DEFAULT_VER=1.9' >> /etc/make.conf
# cd /usr/ports/lang/ruby19
# make install clean
# cd /usr/ports/devel/ruby-gems
# make install clean
# cd /usr/ports/devel/git
# make install clean

2. Heroku のセットアップ

Heroku 専用のコマンドをインストールします。

# gem install heroku
# heroku keys:add
Enter your Heroku credentials.
Email: hyoshida@appirits.com
Password: 
Uploading ssh public key /home/hyoshida/.ssh/id_rsa.pub

 ウェブサービスのセットアップ

1. Rails のアプリケーションを作成

適当な名前のアプリケーションを作成します。

% rails new simple-sg

2. Heroku 向けに編集

ここは少し引っかかりやすいところになります。

Heroku では DBMS に PostgreSQL をサポートしているので、これに合わせた設定が必要になります。

% cp Gemfile /tmp
% vim Gemfile
% diff Gemfile /tmp/Gemfile
8,14c8
< group :preoduction do
<   gem 'pg'
< end
< 
< group :development, :test do
<   gem 'sqlite3'
< end
---
> gem 'sqlite3'
% cp config/database.yml /tmp
% vim config/database.yml
% diff config/database.yml /tmp/database.yml

3. 必要な gem のインストール

Rails アプリに必要な gem のインストールを行います。

今回は Rails 主題の話ではないので、細かい説明は割愛します。

% bundle install --path vender/bundle --without production

4. git の初期化

git に、作成したアプリケーションのファイル群をコミットします。

先ほど追加した gem のファイル群は、コミットする必要がないため除外しています。

% cd simple-sg
% git init
% echo 'vender/bundle' >> .gitignore
% git add .
% git commit -m 'first commit'

 Heroku にアップロード(デプロイ)

1. Heroku 上にアプリケーション枠を用意する

いよいよウェブサービスを公開していきます。

まずは適当なアプリケーション名を Hroku に登録します。

% heroku create simple-sg
Creating simple-sg... done, stack is cedar
http://simple-sg.herokuapp.com/ | git@heroku.com:simple-sg.git
Git remote heroku added

2. リモートリポジトリを追加する

1. で出力された内容を元にして、git にリモートリポジトリを追加します。

% git remote add heroku git@heroku.com:simple-sg.git

3. デプロイする

下記のコマンドで git のコミット内容をリモートリポジトリに反映させるだけで、Heroku 上にウェブサービスが立ち上がります。

% git push heroku master

 おわりに

少し早足になりましたが、このように簡単にウェブアプリケーションをはじめることができます。

次回は、Heroku 上に簡単なソーシャルゲームを作成する手順について紹介したいと思います。

タッチイベントを用いたスワイプ&フリックの実装サンプル

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

スマートフォンのタッチイベントを用いて、画像を横方向にスライドさせる実装をご紹介します。

※PCではマウスイベントで代用可能だと思われます。

※Android/iPhone両方で動作するはずです。

ポイントとしては、スワイプとフリックの動作です。

スワイプ

画面をタッチした状態で指を動かす動作

フリック

画面をタッチした状態で指を「素早く動かす、弾く」動作

この2つの動作を組み込むことで、ネイティブアプリのようなスムーズな動きが実現できます。

 sample.css

body {margin:0;padding:0;}

#slider {
    position: relative;
    width: 320px;
}

#slider a:focus {
    outline: 0;
}

.slider-view {
    position: relative;
    border: 1px solid #bbb;
    width: 320px; /* スライダーで表示するエリアの大きさ */
    height: 360px;
    overflow: hidden; /* 必須 */
}

.slider-container {
    position: absolute;
    top: 0;
    left: 0;
    background-color: black;
	width: 2000px; /* 本来はコンテンツの横幅を取得して動的に設定すべきです */
}

/* スライドするコンテンツ部分 */
.slider-container div {
    position: relative; /* ループ処理に使う */
    float: left;
}

/* チラツキ対策 */
.slider-container {
  -webkit-transform:translate3d(0,0,0);
}

 sample.html

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
  <title>Sample</title>
  <script src="/assets/jquery.js" type="text/javascript"></script>
  <script src="/assets/sample.js" type="text/javascript"></script>
  <link href="/assets/sample.css" media="screen" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="slider">
  <div class="slider-view">
    <div class="slider-container">
      <div id=1><img src="/images/01.jpg" /></div>
      <div id=2><img src="/images/02.jpg" /></div>
      <div id=3><img src="/images/03.jpg" /></div>
    </di>
  </div>
</div>
</body>
</html>

sample.jsではjQueryを利用しているので、jQueryをロードしておきます。

※HTMLタグは都合上全角になっております。実際は半角です。

 sample.js

$(function () {

// 対象となる要素を変数に格納しておく
var $slider     = $('#slider'),
    $container  = $slider.find('div.slider-container'),
    $containerDiv = $slider.find('div.slider-container div');
var distance = 0;    //移動距離を指定するのに使う

// スライド関数
var slide = {
  
  // スライド(進む)
  next: function (index, spd, flick_flg) {
    distance = distance + index;
    slide.scroll(distance, spd, flick_flg);
  },
  
  // スライド(戻る)
  prev: function (index, spd, flick_flg) {
    distance = distance - index;
    slide.scroll(distance, spd, flick_flg);
  },
  
  //移動距離分スクロール
  scroll : function (d, spd, flick_flg) {
    var move = -d
    var env = 'translate3d(' + move + 'px,0,0)';
    
    if (flick_flg) {
      /* フリック時はwebkit-transformプロパティを設定し、滑らかなアニメーションにする */
      transit_property = '-webkit-transform ' + spd + 'ms cubic-bezier(0,0,0.25,1)';
    } else {
      transit_property = 'none';
    }
    
    $container.css({
      '-webkit-transform':env,
      '-webkit-transition':transit_property
    }).bind('webkitTransitionEnd', function(){
       //ここで移動後の終了イベントが取れます     
    });
  }
}

$(window).load(function() {
  var pageX;      //リアルタイムのX座標
  var pageY;      //リアルタイムのY座標
  var startPageX; //スタート時のX 座標の位置
  var startTime;  //スタート時の時間
  var move_time = 0;
  
  /* タッチの開始時のイベント */
  $('#slider').bind('touchstart', function() {
    event.preventDefault();     // ページが動いたり、反応を止める(A タグなど)
    pageX = event.changedTouches[0].pageX;
    pageY = event.changedTouches[0].pageY;
    startPageX = pageX;
    startTime = +new Date();
  });
  
  /* タッチしたまま動かしたときのイベント */
  $('#slider').bind('touchmove', function() {
    var moveX = event.changedTouches[0].pageX; // X 座標の位置
    var absX = Math.abs(pageX - moveX); // 移動距離の絶対値
    var spd = 0.5;
    pageY = event.changedTouches[0].pageY;
    
    /* スワイプ処理 */
      if (pageX > moveX) {
        slide.next(absX, spd);
      } else if (pageX < moveX) {
        slide.prev(absX, spd);
      }
      pageX = moveX;
  });
  
  /* タッチ状態から離れたときのイベント */
  $('#slider').bind('touchend', function() {
  	/* 終了処理が必要ならここに書く */
    /* このイベントは、位置を取得できないので注意 */
    
    var diffX = startPageX - pageX;
    var absX = Math.abs(diffX);
    var mv = 200; //フリック移動距離
    var spd = 700; //フリックスピード
    var now = +new Date(); //現在時間
    var diffTime = now - startTime; //touchstartからの経過時間

    /* フリック処理(touchstartからの経過時間が短い場合) */
    if (diffTime < 400) {
      if (diffX > 0) {
        slide.next(mv, spd, true);
      } else if (diffX < 0) {
        slide.prev(mv, spd, true);
      }
    }
    
    move_time = 0;
  });
});
});

スワイプかフリックかの判定は、touchstart(タッチした瞬間)からtouchend(離した瞬間)までの時間で判定します。

上記サンプルでは400ミリ秒未満の場合はフリックと判定するようにしています(diffTime < 400)

以上です。スワイプとフリックでネイティブアプリのような動きを実現しましょう!

CentOS disk容量 dfとduの値の違い

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

rick No26です。
ついこの間、サーバの容量が圧迫されduコマンドなどで調べても全然使用していないのにdfでみると使用率80%近くいっていたことがあったので、解決方法を紹介します。

環境

CentOS 5.4

dfの値

# df -h
Filesystem サイズ 使用 残り 使用% マウント位置
???秘密???    113G  83G  24G  78%    /
・・・省略・・・
???秘密???     379G  220G  140G 62% /var
これを見ていただくと
「/」と「/var」で約300G使用していることになる。

duの値

# du -h /
これで出てきた最後の「.」は、235Gだった。

疑問

「/var」をduすると220Gで合っていた。
それ以外をduすると、全部で15Gしかなかった。
確かにduで「/」から行った時の合計は235Gだ、
だが、dfで行った時の合計は300G近く、
「/var」があっているので「/」がおかしい、
83Gと15G、、、68Gはいったいどこで使用されているのか?

原因

どうやら削除しても削除しきれていないファイルデータがあるらしい。
# ls -al /proc/*/fd/* | grep deleted
これで出てきたものが削除しきれていないファイルです。
このログをみて、ファイル移動したなとか、プロセス強制終了したなとか思い当たるフシがあるはずです。
そのファイルを操作しているアプリを再起動してみてください。
「/」のdisk使用量が一気に下がるはずです。
自分の場合は、40G程一気に解放されました。

以上、困った時の参考になると幸いです。

鍵がカギで無くなる日

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

先日、米国で開催された「Hackers on Planet Earth 2012」で、とあるデモが行われた。

このデモは、3Dスキャナと3Dプリンタを用い、カギを複製する物だった。

3Dプリンターは、安い物では10万円前後で買うことが出来、1つあたりのコストもわずか数十円とお手軽である。大きな物を作ることは出来ないが、手のひらサイズなら問題なく作成できる。この3Dプリンターは、底辺から輪郭を含めて、すべてを「印刷」することで、オブジェクトを作成する。こうして作成されたオブジェクトは、通常の彫刻や削りでは再現することが難しい、完全につなぎ目の無いモノを作成することが出来る。

次に、3Dスキャナー*1だが、見たモノを見たままに、3Dとして記憶することが出来る。このプリンターと先ほどの3Dプリンターを用いることで、完全にうり二つのモノを作成することが容易に出来る。

 カギの脆弱性

カギが物理形状を成している以上、3Dプリンターの前では、なすすべが無い。

たとえば、ピッキング対策として、採用されているディンプルキーと呼ばれるカギですら、3Dプリンターと3Dスキャナーを組み合わせれば、いとも簡単に同じモノを複製することができる。もはや、物理形状の複雑さだけでは、家を守ることが出来なくなっているのかもしれない。3Dプリンターといえども、磁気情報やIC情報、電波などの物理的に見えるモノ以外の情報を複製できない。もし、真剣に守りたいなら、ディンプルキーではなく、ICカードや磁気カードなどを複数組み合わせたモノを採用する必要が出てくるのかもしれない。

 日本独自のカギ文化

日本独自と言っても過言では無いカギがある。それは、多くの金融機関で採用されており、他国ではほぼ採用されていないもの。そう、印影である。

印影が一致しない限り、現金を引き出すことが出来ない。逆に言えば、印影が一致すれば、現金を引き出すことが出来るもの。それが印影で有り、印鑑だ。通常、印影は印鑑と対になっており、「印鑑をお持ちください」と言われれば、すなわち「印影」を示すことが多い。こうした印影は、当然のように3Dプリンターと3Dスキャナの前では、為す術無く複製されてしまう。欧米のように、簡単には複製できない、筆圧や書き順などに対応した、署名に移行する時期も近いのかもしれない

*1: 安いモノで、300万円ほどする

Rails migrationでbigint型のidカラムを作成

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Railsのmigrationでbigint型のカラムを作成する方法です。

Rails3.1.3, Postgresql 9.1.0 にて確認。

Railsではmigrationのadd_columnでprimary_keyオプションを指定すると、自動でシーケンステーブルとオートインクリメントの付いたカラムを作成してくれます。

class AddColumnIdToUsers < ActiveRecord::Migration
  def up
       add_column :users, :id, :primary_key
  end

  def down
    remove_column :users, :id
  end

end

ですが、これでは型がintegerになってしまいます。型を変更するオプションなども無いようです。

bigintでカラムを作成するため、SQLを直接発行することにします。

class AddColumnIdToUsers < ActiveRecord::Migration
  def up
    execute <<-SQL
      ALTER TABLE users ADD COLUMN id bigint DEFAULT nextval('users_id_seq') PRIMARY KEY;
    SQL
  end

  def down
    remove_column :users, :id
  end

end

Postgresqlでのシーケンステーブルは以下のように作成できます。

class CreateUsersSeq < ActiveRecord::Migration
  def up
    ActiveRecord::Base.connection.execute("create sequence users_id_seq;")
  end

  def down
    ActiveRecord::Base.connection.execute("drop sequence users_id_seq;")    
  end
end

AndroidでGoogle Mapsを表示

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

AndroidでGoogle Mapsを表示するための方法をご紹介します。

 Maps APIキーの取得

Android上でGoogle Mapsを使用するためにMaps APIキーが必要です。

その際、Googleのアカウントと証明書が必要となります。

証明書はデバッグ用のものが以下の手順で取得できます。

$ keytool -list -keystore ~/.android/debug.keystore
...
Certificate fingerprint (MD5): 94:1E:43:49:87:73:BB:E6:A6:88:D7:20:F1:8E:B5:98

パスワードを聞かれますが、入力せずにEnterを押します。

次に以下のサイトにアクセスします。

Android Maps API Key

規約確認のチェックボックスをONにし、

先ほど出力したフィンガープリントを入力して、「Generate API Key」ボタンを押すと、

Maps Keyを取得できます。

 Google APIsインストール

Android Mapsを使用するためにはGoogle APIを使用します。

プロジェクト作成時のビルドターゲットに「Google APIs」が無い場合は、Android SDK and AVD Managerでインストールしてください。

※Google APIsはプラットフォーム別に複数あるので、開発に使うプラットフォームのものは必ずインストールします。 まあ全部インストールしちゃってもいいと思います。

1. Android SDK and AVD Managerを開く

(開発にEclipseを使用している場合は、[ウィンドウ] – [Android SDK and AVD Manager] などで開けます)

2. Available PackageでインストールするGoogle APIsにチェックを入れる

3. [Install Selected]をクリックしてインストール

 AVDの作成

Google APIs用のAVD(Android Virtual Device)を作成しておきます。

Google APIsをインストールした時と同じようにAndroid SDK and AVD Managerで作成します。

1. Android SDK and AVD Managerを開く

(開発にEclipseを使用している場合は、[ウィンドウ] – [Android SDK and AVD Manager] などで開けます)

2. Virtual Devicesで[新規]をクリック

3. 「名前」は適当なものを入れ、「ターゲット」には開発で使用するGoogle APIsのプラットフォームを入力して、[Create AVD]をクリック

 サンプルプロジェクトの作成

最後に簡単にGoogle Mapを表示するためのサンプルプロジェクトを紹介します。

新規プロジェクトの作成では、ビルドターゲットに先ほどインストールしたGoogle APIsを選択します。

package com.exapmple.androidmaps2;

import android.app.Activity;
import android.os.Bundle;

import android.os.Bundle;
import com.google.android.maps.*;
 
public class AndroidMaps2 extends MapActivity {
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MapView map = new MapView(this, "[Android Maps API Key]");
        map.setEnabled(true);
        map.setClickable(true);
        setContentView(map);
    }
 
    @Override
     protected boolean isRouteDisplayed() {
        return false;
    }
}

[Android Maps API Key]に準備で取得したAndroid Maps API Keyを入力して下さい。

AndroidManifest.xmlは下記のようになります。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.androidmaps" android:versioncode="1" android:versionname="1.0">
    <uses-sdk android:minsdkversion="1.5" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AndroidMaps" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
		 <uses-library android:name="com.google.android.maps" /> ←追加
    </application>
    <uses-permission android:name="android.permission.INTERNET" /> ←追加
</manifest>

これでGoogle Mapが表示されます!

リアルタイム多人数じゃんけんゲーム「JANG Battle」をリリースしました

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

 概要

  • Node.js+socket.io+expressアプリはとっても簡単
  • herokuにデプロイしたら予想外のところで詰まった
  • 格闘ジャンケンゲームJANG Battle!みんな遊んでね!

 リアルタイム通信するアプリを作ったことありますよね

 こんにちは,Rails厨のわたなべ(hackugyo)です.

 ところでみなさんはNode.jsって知っていますか.Node.jsのヴァージョンを管理するソフトにナベっていうのがあるんですが,私はワタナベなのでライバル視しています.

 node.js+Socket.IOのNon-blockingI/O環境を見ると,一刻も早くリアルタイムに通信するアプリを作りたくなりますよね.私もそうです.ざっと見たところ,リアルタイム通信ときいて一番にみなさんが思いつくのはチャットアプリのようで,node.jsの前開発リーダRyan Dahlさんもgithubでサンプルを公開されています(https://github.com/ry/node_chat).

 私も学習のためにチャットアプリを作ろうと思ったのですが,リアルタイム通信といえばゲームだよなと思い直し,途中から格闘ゲームに切り替えて作りました.といっても中身はほとんどチャットで,パンチ・ガード・ジャンプキックの3つのうちどれかをコマンド選択して,相手のコマンドとの相性で勝敗を決めるという,簡単なものです.

こちらがアプリです

 対戦格闘じゃんけんゲーム

 JANG Battle!!

  1. ぐー・ちょき・ぱーから手を選びます
  2. 他のプレイヤの選んでいる手に勝っていれば,1点ゲット
  3. 連打によってどんどん点を稼げます
  4. 他のプレイヤがリアルタイムに手を変えるので,同じ手を連打していても勝てないかもしれません
  5. 20点とったら勝ちです

 このアプリの作成にあたっては,ゲーマの友人の今井晋さん(facebookページ)より企画・アイデアをいただきました.貴重なアイデアを無償で公開していただき感謝します.

 勝敗判定など,今後もアップグレードを続けていきます!

(ソースもこちらで公開します.https://github.com/hackugyo/ChatJangBattle

 ヘロクにデプロイする

 さて,せっかく作ったのですから,localhostで動かすだけでなく,公開してみんなに遊んでもらいたいものです.チャットアプリもそうですが,リアルタイム通信の面白みを知るにはやはり多くのクライアントをさばく様子を見たいわけです.ましてや今回は対戦型格闘ゲームを作ってしまったので,ひとりで複数タブからパンチ……ガード……していてもむなしいだけです.

 最近は恐ろしいことに,Paasなホスティング環境が無料でたくさんそろっています.DotCloud, Cloud Foundry, OpenShift, Node Ninja, Nodejitsu, etc.(node.js対応のホスティング環境の一覧はこちらにまとまっています).いまやWebアプリを試すのにも,localだけで満足する理由はほとんどなくなりました(セキュリティまわりの問題はありますが).さあ,どこにホスティングさせてもらいましょうか?

 さあ,私はRails厨なので、ここでもちろんHerokuを選びます.HerokuはRubyの作者まつもとゆきひろ氏をチーフアーキテクトに迎えるなど,Rubyに対しなみなみならぬ優しさをもったプラットフォームです.言語としてはほかにもScala, Java, Pythonなどにも対応しており,もちろんnode.jsもOKです.

herokuデプロイ時の注意

masterブランチをpushすること

 gitを利用し,ふだんのヴァージョン管理とほとんど変わらない気軽さでデプロイできるのが,Herokuの大きな魅力ですが,ここにはちょっとした心理的落とし穴があります.

 私は最近,gitのブランチモデルについて勉強し,release / develop / featureなどのブランチをごりごり切り替えて使っているのですが,その影響で,herokuに大してもうっかり

$ git push heroku release

とreleaseブランチをpushしてしまったのです.これではさしものherokuも理解してくれません.ここは,正しくは

$ git push heroku relase:master

とすべきでした.あるいは,おとなしくmasterブランチをrelease目的に使ってもいいでしょうね.

ポート番号には注意

 ローカル環境でWebアプリを試して,それをherokuにデプロイする場合,気をつけたいのはポート番号の設定です.ほかにも,Procfileを書くなどの追加点はありますが,既存のソースに手を入れるのはつい忘れがちです.

 さて,ローカル環境で試したWebアプリには,主に2カ所,ポート番号を書いているところがあります.

  1. サーバサイドのjs
  2. クライアントサイドのjs

 あたりまえですね.

 サーバサイドは簡単です.app.jsのここを

var port = 5000;
app.listen(port, function(){
  console.log("Express server listening on port %d in %s mode", 
    app.address().port, app.settings.env);
});

こう変えるわけです.

var port = process.env.PORT || 5000;
app.listen(port, function(){
  console.log("Express server listening on port %d in %s mode", 
    app.address().port, app.settings.env);
});

これで,herokuデプロイ時にはprocess.env.PORTの値が使われるようになります.(デフォルトポートが5000なのは,foremanというマネージャに合わせたためです)

 問題はクライアントです.jadeからclient.jsを切り出したのはいいのですが,その中でこういう記述をしていました.

var socket = io.connect('http://localhost:5000/chat');

// 一覧表示要請を検知し,ログを表示する
socket.on('chat.list', function(list) {
  ...
});

ソケット接続を要求するためのコードですが,ポート5000がまるのまま出てきていますね.io.connectを使った書きかたは,node.jsのv0.7以降で登場したものだそうで,ネットを見てもあまり情報がありません.

 ここは素直にこう変えます.

var socket = io.connect('/chat');

// 一覧表示要請を検知し,ログを表示する
socket.on('chat.list', function(list) {
  ...
});

これで,ポートやホスティング先URLに関係なく,正しい接続要求をすることができます.

 みなさんもnode.jsでherokuに楽しいアプリを作ってください!

 ご参考

  1. herokuへのnode.jsアプリのデプロイについては,本家ブログに記事があります. https://devcenter.heroku.com/articles/nodejs
  2. node.jsじたいの解説は, Web+DBPRESS vol.58(技術評論社, 2012)の特集”Node.js実践入門”がたいへん参考になります.著者は名村卓(@snamura)さんです.
  3. チャットアプリのUIについては,いくつもライブラリが公開されています.最近だとBaloons.IOなどかっこいい. https://github.com/gravityonmars/Balloons.IO
  4. テンプレートエンジンにはexpressのデフォルトのJadeを使いました.こちらのコンヴァータは便利:http://html2jade.aaron-powell.com/
  5. 開発環境はEmacsでしたが,Nideもちょっと触りました.面白いですね.http://coreh.github.com/nide/

ここ最近使ってみたiOSのライブラリまとめ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

最近になって仕事としては約1年ぶりにiOSアプリの開発をしております。

その間にiOSが5になったり、iPhone4Sが出たりと状況が変わっており一瞬浦島太郎気分を味わったり、そんな自分がここ最近触ってみたiOSのライブラリを紹介したと思います。

 AFNetworking

https://github.com/AFNetworking/AFNetworking

ネットワーク用のライブラリです。今までネットワークのライブラリはASIHTTPRequestを使っていましたが、開発が止まってしまい、新たな案件で使い続けるのも不安だったのでこっちに乗り換えてみました。

通信終了後の処理をブロックで書けるのが何気に便利ですね。

XMLやJSONをダウンロードするためのクラスも用意されております。

JSONをJSONKitと組み合わせて使ってみましたが、特に意識することなくダウンロードしたJSONをNSDictionary、NSArrayの形で展開してくれてすごく便利でした。

 SVProgressHUD

https://github.com/samvermette/SVProgressHUD

ライブラリを取り込んで、下の1行を書くだけでクールなインジケータを出すことができます。

[SVProgressHUD showWithStatus:@"ダウンロード中" maskType:SVProgressHUDMaskTypeGradient];

 OHAttributedLabel

https://github.com/AliSoftware/OHAttributedLabel

これを使うと下のように1つのラベルで色を変えたり、文字のサイズを変更したり、リンクを貼ることが出来ます。

コードはこんな感じです。

    NSString *text = @"赤文字、青文字、大文字、太字、http://doruby.kbmj.com/";
    NSMutableAttributedString *attrStr = [NSMutableAttributedString attributedStringWithString:text]; 
    [attrStr setTextColor:[UIColor redColor] range:[text rangeOfString:@"赤文字"]];
    [attrStr setTextColor:[UIColor blueColor] range:[text rangeOfString:@"青文字"]];
    [attrStr setFont:[UIFont systemFontOfSize:16] range:[text rangeOfString:@"大文字"]];
    [attrStr setFont:[UIFont boldSystemFontOfSize:12] range:[text rangeOfString:@"太字"]];
    _label.attributedText = attrStr;
    [_label addCustomLink:[NSURL URLWithString:@"http://doruby.kbmj.com/"] inRange:[text rangeOfString:@"http://doruby.kbmj.com/"]];

一つのラベルで色を変えたり、リンクを貼ることが出来たり便利なライブラリですが、いくつか何点もありました。

  • iOS5でテーブルビューのセルで使うとカクカクになりやすい。
  • 複数行表示させると標準のUILabelに比べて行間が広い。

売買される個人情報

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

皆さんは、自分の個人情報について、どれくらい気を使っているだろうか。その昔、メールと名前、性別がセットで1件当たり○○円で売買しているなんて記事が、ネットに流れたこともあった。現在は、そういったセット販売の価格が暴落し、単純に1件でいくらという価格出はなくなりつつあると聞く。

 売買される個人情報の価値

まず、売買される個人情報について考えてみよう。売買される個人情報には、いくつかのランクがあり、まず、単なるメールアドレスだけの場合。これはほとんど無価値と呼ばれており、数十万レコード有ったとしても、その価値は高くても数千円止まり。下手をすると、数百円ってこともある。これは、そのメールアドレスが本当に現在も使われているか(流通しているか)が確定していないためだ。もし、これが、すべて使われている場合は、10倍程度の価値がつく。ただし、本当にすべてのメールアドレスが使われていれば・・・の話だ。また、それがフリーのメールアドレスなのか、それとも、企業が使っているメールアドレスかによっても、価値が変わる。もし、企業が使っているメールアドレスの場合、おいそれと変更するわけにいかず、使い続ける可能性が高い。逆に、フリーメールの場合は、簡単に変えられるため、使い続ける可能性が低く、大量に迷惑メールを受信した場合は、そのメールアドレスを捨てる可能性が十分に有る。そのため、企業とフリーのメールアドレスでは、その価値が大きく異なる。ただし、メールアドレスだけでは、先ほども書いた通り、あまり価値はなく、それ以外にヒモ付けされたものがあれば、その価値はぐっと上がる。

先ほど、企業のメールアドレスの場合は、価値がフリーアドレスに比べ、高いと書いたが、これは変更されない事と、もうひとつ理由がある。それは、その企業に属していることがほぼ確定しているためだ。.co.jp の場合、その企業に属しているもしくは、何らかの関係者であるため、個人を特定しやすい。たとえば、katayama@appirits.com といった場合、「アピリッツに勤めている片山」さんとわかるわけだ。このように、個人を特定する事ができる情報はきわめて価値が高い。これに、クレジットカード情報と性別、電話番号が含まれていれば、1件あたり10円前後の価値があるかもしれない。1件10円と聞くと、あまり価値がないように感じられるかもしれないが、数万件集めれば、ちょっとした小遣い稼ぎになる。

先ほども述べたように、個人を特定する情報は価値が高いが、逆に個人を特定できない情報はあまり価値がないと書いた。最近では、買い取り時には金銭が発生しないケースが有る。このケースでは、どんな状態(情報)で有っても、個人情報を渡す際には一切の金銭授受が発生しない。では、どのように行うかというと、アフィリエイト型と呼ばれる方法だ。この方法では、先ほどのように、1件いくらといった相場は存在しない。たとえば、Aさんの情報を含んだものを、アピリッツ商事に私が渡したとする。この時点では、金銭授受が発生しない。Aさんがアピリッツ商事で100万円の買い物をするとする、買い物額の25%である、25万円が私の懐に入る。Aさんが、アピリッツ商事で買い物をし続ける限り、延々と私の手元には、購入金額に応じ数%〜20%前後が振り込まれる。個人情報を渡した時点で金銭授受が発生しない分、売り逃げはできないが、システム上いくらの売り上げが有ったのかを確認することができ、そして、いくらの振り込みが有るのかを確認することができるため、個人情報の売り手にとって非常においしい仕組みになっている。仮に、渡した個人情報が10万件有ったとして、そのうち1%、つまり、1千人が、毎月1万円の買い物をした場合、何もしなくても、毎月25万円の小遣いだ。

とはいえ、10万件ものメールアドレスや個人情報を集めるのは、相当骨の折れる作業だ。しかも、目の前に有るような個人情報をわしづかみにして、売り払うと、某証券会社のような状態になりかねない。しかも、売却額よりも損害賠償額の方が、はるかに大きい状況では、割に合わない。そこで、個人情報を集めてる人に聞いた、さまざまな方法を書いて見よう。

 マルウェアを用いる方法

世の中には、マルウェアを自分好みにアレンジしてくれるサイトがいくつかある。マルウェアに感染させ、中に含まれるさまざまな情報を、根こそぎ奪ったり、キーロガーを仕掛けて、さまざまな情報を抜く方法も有る。特に、銀行や証券会社のIDとパスワード、名前セットは非常に高く売買されている。

 メールサーバ の仕様上の問題を突く

メールサーバには、受け入れられるメールアドレスをメール本文を送信する前に送信者に返答する仕様が有る。辞書を使って、大量に存在していると思われるユーザを片っ端に調べることで、その企業やISPに所属しているメールアドレスを大量にかつ確実に入手することができる。

 SQLインジェクションを用いる

最近、中国や韓国から、日本のネットショップが狙われている方法だ。それも、かなり自動化されており、ほぼ100%人が介在していない。最も今用いられている方法の一つだ。

 同業他社の情報をいただく

こういった情報を収集している企業は数多く存在している。そういった企業のサイトには、セキュリティ対策が施されておらず、簡単にgoogle や yahoo などの検索エンジンに引っかかるケースがある。こういった情報をもとに、効率良く情報を取得する方法も有る。

大量の個人情報を集めたら、それを、適切なフォーマットに並び替え、CD-RやUSBメモリなどに入れて、顧客に渡す。メールを用いても良いのだが、足が付いてしまう危険性があるため、フリーのwebメールで、多段串を経由するか、複数の国外踏み台を経由してのアクセスなど、よほど入念に対策を施した状態でなければ、メールで送信することは無い。

今回は、筆者が複数の関係者から聞いた話をまとめて書いた。個人情報がどのように売買されているのか、少しは興味を持ってくれただろうか。くれぐれも、加害者、被害者ともに、ブラックマーケットに関わることの無いように。といっても、被害者になってることすら、気づかないんだけどな。

ECサイト構築パッケージ「エレコマ」の初期設定@Ubuntu 10.10

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。


よしだです。

前回の記事』では、エレコマのインストール手順を紹介しました。

今回はインストール後の初期設定について書いていきたいと思います。

 概要

エレコマのロゴ

今回はエレコマはインストール後に行う必要最低限な設定を紹介します。

主な設定は以下の3つになります。

 1. 管理者ユーザの登録

 2. ショップ情報の登録

 3. 商品情報の登録

それでは早速設定操作に移りましょう。

 1. 管理者ユーザの登録

エレコマに販売したい商品を登録するには、管理画面へアクセスする必要があります。

この管理画面にアクセスするためのユーザを管理者ユーザと呼びます。

エレコマインストール直後は、管理者ユーザが登録されていない状態なので、新しく登録します。

a. エレコマディレクトリへ移動

前回の記事でエレコマをインストールしたディレクトリに移動します。

% su - ec
ec% /usr/local/elecoma

b. 管理者ユーザ ID、パスワードの変更

管理者ユーザの ID とパスワードを任意の物に変更します。

デフォルトの ID とパスワードは admin、pass となっています。

ec% vim test/fixtures/admin_users.yml

c. 管理者ユーザの登録

下記のコマンドでデータベースに管理者ユーザの情報を登録します。

ec% rake db:fixtures:load FIXTURES=admin_users RAILS_ENV=production

d. 登録確認

登録できたことを確認するために、管理画面へのログイン画面から実際にログインします。

ログイン画面へは http://(サーバの IP アドレス)/admin からアクセスできます。

http://doruby.kbmj.com/hyoshida/files/elecoma_login.png

(ログイン画面です)

http://doruby.kbmj.com/hyoshida/files/elecoma_admin.png

(正常にログインできると管理画面にアクセスできます)

無事にログインできれば次のステップに進みます。

 2. ショップ情報の登録

商品を登録する前に、ショップ情報を入力しておきます。

ショップ情報が入力されていないと一部のページが機能しなくなるので注意が必要です。

ショップ情報を登録するには、管理画面のメニューから「店舗情報」⇒「SHOPマスタ」と辿って下さい。

登録画面で社名や住所、メールアドレスなどの必要な情報を入力します。

http://doruby.kbmj.com/hyoshida/files/elecoma_admin_shop.png

(ショップ情報を入力して登録します)

 3. 商品情報の登録

いよいよ商品情報の登録に移ります。

エレコマでは、[商品]+[規格]の組み合わせをひとつの商品情報として扱っています。

  • ◎[商品]には、商品名や画像、紹介文が関連づけることができます。
  • ◎[規格]には、たとえば同名商品の「色違い」を赤、青、緑の分類として関連づけることができます。

まず[規格]の登録方法から紹介します。

a. [規格]の登録

規格登録画面は「商品管理」⇒「規格登録」からアクセスすることができます。

ここでは例として、色違いの商品を表現するための規格と分類を登録していきます。

  1. 規格名に「色」入力して登録します。
  2. 登録した規格と同行にある「分類登録」リンクへ飛びます。
  3. 規格分類名にそれぞれ「赤」「青」「緑」と入力した3つの分類を登録します。

これで[規格]の登録は完了です。

b. [商品]の登録

商品登録画面は「商品管理」⇒「商品登録」からアクセスすることができます。

ここから商品名や画像、紹介文などを順番に入力していきます。

すべて入力し終えたら登録を済ませます。

c. [規格]+[商品]を組み合わせる

最後に先ほど登録した[規格]と[商品]を組み合わせて、ひとつの商品情報に仕上げます。

  1. 「商品管理」⇒「商品マスタ管理」から先ほど登録した商品を探します。
  2. 対象商品の行にある「規格」リンクにアクセスします。
  3. 赤、青、緑の規格のうち、有効にしたい規格にチェックを入れ、商品コードや価格を入力します。

あとはこれを登録するだけで商品情報が完成します。

できあがった商品は、「商品マスタ管理」の「確認」リンクから販売サイト視点で確認することができます。

 最後に

前回と今回で、エレコマのインストールから初期設定までを簡単に紹介しました。

説明が荒削りになっている部分もあるかとは思いますが、少しでも参考になれば幸いです。

一緒に始めようSencha Touch 2.0 入門編: 第1回 Sencha Touchを導入しよう

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめまして、2012年新卒として入社致しました、だーますと申します。どうぞよろしくお願い致します。

今回はスマートフォンアプリのような操作性を持つWebアプリ開発フレームワークである”Sencha Touch 2.0″について解説させていただきます。

 Sencha Touchって何?

Sencha Touchとは、米国のSencha社が開発した、HTML5ベースのWebアプリ開発フレームワークです。

具体的な特徴

・スマートフォンやタブレットのWebブラウザで動く、ネイティブアプリのようなアプリを作れる!・iOS、Androidのどちらでも動作する!・HTML5って書いてはあるけど、JavaScriptさえわかれば開発できる!・AjaxやJSONPリクエストもバッチリ送れる!・無料で利用でき、しかも商用もOK!

対応OS

・iOS 4.0以上 (iPhone、iPod touch、iPad)

・Android 2.2以上

・BlackBerry

・テスト用:WebKitブラウザ (Chrome、Safari)

Windows Phoneや、WebKitでないブラウザ(IEやFirefox、Opera等)では使えません。

どんなアプリが作れるの?

Sencha社公式のデモアプリ集採用例集をご覧になると良いかと思います。(注:WebKitブラウザで見てください)

ここにあるアプリ、全部JavaScriptで書かれています。すごいですよね!

 Sencha Touch 2.0を入手する

それでは早速、Sencha Touch 2.0のライブラリを入手してみましょう。

  1. Sencha Touch 2.0のダウンロードページに飛びます
  2. Open Source Version(GPLv3ライセンス)かFree Commercial Version(商用版・独自ライセンス)のどちらかを選び、ダウンロードします。本稿執筆時点でのバージョンは2.0.1.1です。
  3. 落ちてきたZIPファイルを展開します

これでOKです。

開発環境はどうするの?

エディタ

JavaScriptが書ければなんでもOKです。私はMacでEclipseにAptana Studioを入れて使っています。

ブラウザ

PC上で動作確認をするならば、WebKitブラウザーを用意してください。

デベロッパーツールを画面横分割して使えるChromeがおすすめです。

少し前まではSafariの方がSencha Touchの動作がなめらかでしたが、最近はChromeも追いついて来ました。

Webサーバー

スマートフォンやタブレットから動作確認するなら、PC上にWebサーバーを立てておくと楽でしょう。

Mac OS Xで、有線でネットワークに接続しているなら、Web共有とAirMacでのインターネット共有を併用すれば簡単にできます。

[2012/11/13追記]

OS Xの最新版Mountain Lionでは、システム環境設定からWeb共有の設定ができなくなっています。

しかし、機能が消滅したわけではなく、以下のサイト等を参考に手動で設定可能です。

うまでしか Blog: Mountain LionにおけるWeb共有の消滅と403 Forbiddenの解決策

 とりあえず触ってみよう!

ライブラリーを入手したら、早速ソースコードを書いてみましょう。

適当なところにフォルダを作って、そこに先ほど展開したSencha Touchのフォルダごと入れてください(本稿ではsencha-touch-2.0.1.1 とします)。

index.html

作ったフォルダにindex.htmlというファイルを作り、次のように記述してください:

<!DOCTYPE html>
<html>
    <head>
        
        <title>Sencha Touch App</title>
        <link rel="stylesheet" type="text/css" href="sencha-touch-2.0.1.1/resources/css/sencha-touch.css" />
        <script type="text/javascript" src="sencha-touch-2.0.1.1/sencha-touch-all-debug.js"></script>
        <script type="text/javascript" src="app.js"></script>
    </head>
    <body></body>
</html>

“sencha-touch.css”は、UIのデザインを指定したスタイルシートです。”sencha-touch-all-debug.js”が、Sencha Touchのライブラリです。そして”app.js”が我々が作ろうとしているアプリの本体で、これから記述します。

bodyタグの中身は、何も書かないでください。bodyの中身は、ライブラリによってすべて動的に生成されます。

app.js

同じフォルダにapp.jsというファイルを作り、次のようにしてみましょう:

Ext.application({   
    launch: function() {
        Ext.Viewport.add({
            xtype: 'panel',
            items: [
            {
                xtype: 'label',
                html: 'Hello,world!'
            }]
        });
    }
});

これをPCのブラウザで確認してみましょう。以下のようなページができるはずです。

上にいくつかメソッド・関数が出てきていますが、

  • Ext.application(): アプリの大元締め
  • launch: function(): アプリが実行されて一番最初に呼び出される関数
  • Ext.Viewport.add(): 画面にUIを追加するメソッド

であると思っておいてください。

Sencha TouchのUIはオブジェクトの形式で記述する

上記のExt.Viewport.addの中身を見てみてください:

{
    xtype: 'panel',
     items: [
    {
        xtype: 'label',
        html: 'Hello,world!'
    }]
}

となっていますね。この部分でUIを定義しています。まるでJSON形式みたいな記法ですね。Sencha Touchではこの記述方法をたくさん扱いますが、Sencha Touchを修得する上で覚えられると思います。カンマやコロンを忘れたりするとちゃんと動きませんので、忘れないように。

具体的に見てみましょう。xtype: ‘panel’ となっているのは、panel形式のUIコンポーネントを配置する、という意味です。そしてこの panel コンポーネントには、次の items に記述することでサブコンポーネントを追加できます。

items の中には xtype: ‘label’ が入っており、その次の行の html: ‘Hello, world!’ がラベルとして表示する中身です。(html なのでタグによる記述も可能です)

サブコンポーネントをちょっと増やして遊んでみましょう。app.jsを以下のように書き換えてみてください:

Ext.application({
    launch: function() {
        Ext.Viewport.add({
            xtype: 'panel',
            items: [
            {
                xtype: 'label',
                html: 'Hello,world!'
            },{
                xtype: 'button',
                text: 'ボタンです'
            },{
                xtype: 'textfield',
                placeHolder: 'テキストボックスです'
            }]
        });
    }
});

実行結果です:

キャプチャプラグインの都合上ボタンの右端が切れてしまいましたが、ちゃんと表示はされるはずです。他にも様々なコンポーネントがあります。これらについては、次回以降説明することにします。

 ナビゲーション (Navigation View)

もうちょっとiOSライクなUIを見てみたいですね。app.jsを次のようにしましょう。階層が増え始めましたが、Sencha Touchではよくあることなので、慣れてください:

Ext.application({
    launch: function() {
        Ext.Viewport.add({
            xtype: 'navigationview',
            items: [{
                xtype: 'panel',
                title: 'First View',    // ナビゲーションバーに表示する文字列
                items : [
                {
                    xtype: 'label',
                    html: 'This is First View'
                },{
                    xtype: 'button',
                    text: 'Push Next View',
                   
                    // ボタンにイベントを設定
                    handler: function() {

                        // このコンポーネントの2つ上の navigationview で定義されたメソッド
                        this.parent.parent.push({
                            xtype: 'panel',
                            title: 'Second View',
                            items: [{
                                xtype: 'label',
                                html: 'This is Second View' // 画面遷移後にナビゲーションバーに表示する文字列
                            }]
                        });
                    }
                }]
            }]
        });
    }
});

これを実行すると次の画面になります:

ここにある、”Push Next View”というボタンを押すと…?!

アニメーションして上のような画面が現れます!もちろん、”Back”をタップすると、前の画面に戻れます。

これがiOSアプリでよく見られる、ナビゲーションビューというものです!

上記のソースコードではまず、一番上のコンポーネントに xtype: ‘navigationview’ を設定しています。そこで最初に表示するコンポーネント xtype: ‘panel’ を items に記述しています。その panel の中には、ナビゲーションビューがそのコンポーネントを表示している際に画面上部のバーに表示する文字列を表す title と、さらにそのサブコンポーネントとして items 内に xtype: ‘label’ と xtype: ‘button’を記述しています。

この button に注目してください。handler: function() というのがあります。ここで、そのボタンが押された時に実行する処理を記述しています。これでボタンがただの飾りから、ちゃんと動作するコンポーネントに進化しました。

さらにその handler の処理ですが、this.parent.parent.push というメソッドがあります。これは、このボタンの二つ上のコンポーネントである navigationview に定義されている push というメソッドを指しています。これはナビゲーションビューで新しい画面を呼び出すメソッドです。今回はこの中に直接新しく xtype: ‘panel’ を記述しています。”Back”ボタンは自動で生成されるので、こちらで特に記述する必要はありません。

このように、JavaScript を記述するだけで、iOSライクなインターフェースを実現することができるのです!すばらしいですね!

これらのコンポーネントは、動的に生成して表示することも可能です。これは、今後説明させていただいます。

今回はごく簡単な説明のみさせていただきましたが、様々なUIコンポーネントを組み合わせることにより、リッチなUIを持ったスマートフォン向けWebアプリケーションを作ることができるようになるのです。とても素晴らしいですね!

 次回は

様々なUIコンポーネント、そしてそれらをクラスとして定義する方法について説明する予定です。どうぞお楽しみに!

意外に知らない人が多い!Skypeを使うときに気をつけたい話(1) ~オフラインが招くトラブル~

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

 2012年新卒で入社いたしました、ずんです。僭越ながら今回初めてDoRubyにて記事を執筆致します。よろしくお願いします。今回はSkypeを使っていると誰でも必ず遭遇したことがあるであろうトラブルについて。check it out!!

 モバイル・インターネットの急速な発展のおかげで最近はPCだけでなくスマートフォンでも使えるようになり、より手軽に、無料で、高音質・高画質で、電話やテレビ電話に代わるコミュニケーションツールとなったSkype。

 最近ではビジネスの現場でも使われるようになった。

 社内での連絡を内線やメールを使わずに、Skypeで全て済ますことで組織運営の簡略化を図る例も珍しくない。

 しかし便利な反面、サーバが存在せずP2PでメッセージをやりとりするSkype特有の性質を知っておかないと大変なミスを引き起こすことになるかも……。

 意外に誰も気にしない問題;相手がオフラインの時に送信されたメッセージはいつ相手に届くのか

 パソコンなり、スマートフォンなりでSkypeを使ったことがある読者諸兄は多いと思う。そんな読者諸兄は一度はこういう怪奇現象に巻き込まれた事があるだろう。

※ここから、とある事の報告を頼まれて、それをSkypeのメッセージを使って送ろうとしているルークと、

仕事を頼み、報告を受け取ろうとしている上司のオビワンが居るとしよう*1

 金曜日、オビワンは仕事が落ち着いており、家族と週末を使って旅行にいくため有給休暇を取って会社に居ない。

 そこで、ルークはオビワンからの仕事を一手に引き受け、月曜日に結果をなんらかの形で報告するように指示されている。

 しかし、ルークは月曜日に有給休暇を申請しているので、金曜日に退社する時までにオビワンに何らかの方法で仕事の結果についてメッセージを残しておかなくてはならない。

状況まとめ
  1. ルーク(部下)は金曜日に出勤しているが、月曜日は居ない。
  2. オビワン(上司)は金曜日は居ないが、月曜日に出勤する。
  3. オビワンは、ルークに対して仕事の報告をメールでもSkypeでもなんでもいいので、なんらかの形で月曜日朝に出勤したときに分かるように指示している。
  4. オフィスが多くの部屋に分かれている上、在宅勤務のスタッフも居るため、普段の業務中のコミュニケーションはSkypeのテキストチャットを用いている。
  5. 2人のSkypeのアカウントは仕事用に作ったため、出勤時以外はSkypeにログインしない。

 さて、滞り無くタスクを終え、オビワンに報告を書いて退社しようとするルーク。

 普段の業務でもSkypeで、仕事の指示・報告・連絡・相談からファイルのやりとりまでやっているため、普段通りSkypeのテキストチャットでオビワン宛に報告を書いて退社した。

 そして火曜日。久々の3連休を充実して過ごし元気一杯で出勤したルーク。

 しかし彼は出勤直後にオビワンから怒られてしまう。

「報告が、届いていないじゃないか。月曜に来たときに分かるように報告を残せと言ったはずだ!」

 しかし、ルークは間違いなく金曜の退勤時にオビワンに対しSkypeで報告を投げたはずである。だが、月曜日にオビワンが確認したところそれが届いていなかった。

 彼曰く、火曜日の朝になって、たった今届いたというのだ。何故だろうか。

 なぜ、届かなかったか

 さて、間違いなくルークはオビワンに報告を送ったのは間違いない。*2

 しかし一方で、それがオビワンに対して月曜日に届いていなかった。

 その理由は、Skype特有の性質にある。Skypeでは相手がオフライン時に送られたメッセージはどのように相手に届けられるのだろうか。

 Skypeは、メッセージを中継するサーバが存在しない

 Skypeにはメッセージを中継するサーバが存在しない。そう、存在しないのだ。*3

 一般的なインスタントメッセンジャーのように、サーバ&クライアントの従属関係があって、メッセージを中継するサーバが存在している場合は、

相手がオフラインの時はメッセンジャーのサーバ側でそれを一旦預かって貰い、相手がオンラインになった瞬間、

「送り側がオンラインか否かにかかわらず」オフラインメッセージという形でメッセージが送信される。

 SkypeはP2Pでメッセージや音声、ビデオをやりとりしているためそれが無い。

 なので、メッセージが送受信されるタイミングは「お互いがSkypeを起動している」状態でないとつながらないのだ。(P2Pについては次回)

 「仕組み」を簡単に書くとこういうことではないだろうか。

ルークが、オフラインのオビワンにメッセージを送る。

 ↓

オビワンはオフラインであるため、メッセージは送信されずにルークのPCのローカルにメッセージが一旦保存される。

 ↓

ルークがPCの電源を入れ、Skypeを起動している間、オビワンがPCの電源を入れ、Skypeを起動すると、それをルークのPCのSkypeが検知して、ローカルに保存したメッセージを送信する。

 ↓

オビワンがメッセージを受信する。

 改善方法

  1. もし、グループでSkypeを使っているなら、メッセージ中継用のアカウントをグループ内に建てる。
    • それを常にオンライン状態に維持する。
    • グループ内で、その中継用アカウントが全ての発言ログを記録するため、自分がオフライン中のグループ内での他人の発言は、その中継用アカウントから取ってこれる。
  2. 相手がオフラインの時はメールで送る。
    • なんだかんだ言って、メールは必須ですよね。
  3. 同じ社内でやり取りしているなら、文書にして紙で置いておく。
    • 時にはアナログに。

 ちなみに、上記のようなトラブルは割と頻繁にある話で、僕の友人でも

「まさに同じ現象があった!でもなんで!?どういうことなの!?すごい大事な事を書いたのにすごい遅れて届いた!!」と泣く方がそれはもう多く……。

 つまり何が言いたいかというと、インターネットがだいぶ発展してきて、昔はかなり手間がかかっていたことを、クリック1つで簡単に、誰でも、しかも無料でできる世の中になりました。

 しかし前提としてまず自分の使うツールの性質をよく理解しておきましょうね……という話でした。

 次回予告

技術的な話~Skypeはどんな通信をしているのか?~

 次回は、今回の話を踏まえて

「じゃあ、Skypeでは起動してからどのような通信を行なっているか」という事を、「プロトコル」と「P2P」の話を交えつつなるべくわかりやすく書いてみようと思います。

 普段皆様何気なくSkypeを使っていると思いますが、きっと気になったことがあるかも?

 少しでもweb技術に詳しい方なら「P2P」という単語を聞いたことはあるとは思いますが、じゃあ実際SkypeにおいてP2Pがどのように使われているかは意外に知らないものです。

 ならば折角だし一緒に詳しく掘り下げてみましょう!

 大丈夫。TCPとかUDPとか聞いたことない人でも解るように書きますよ!

 DoRubyはどちらかというと技術者向けの記事が多いですが、僕はちょっと趣向を変えて、

IT技術に詳しくない人でもわかりやすく、できれば普段何気なく使っているIT関連の物の仕組みについて関心を持ってもらえるような記事を書いてみたいと思います。*4

 お便り

 単なる感想や「こんな事聞きたい・知りたい」などのお便りをお待ちしております。次の記事の種になるかもしれません。

 種にならなくとも1通でも届くと中の人が喜びます。次の記事を書くモチベーションにつながります。

※返信は致しかねます。また、頂いたメールやコメントは記事内で引用させていただく事があります。

mailto:zun.doruby@gmail.com

*1: この記事をアップした翌朝、何人かの同期に「なぜルークとオビワンなのか」と聞かれたが、単にスター・ウォーズが好きなだけである。

*2: 「普通こういうモノはメールか文書で残すものじゃないのか」というツッコミは、申し訳ないがこらえていただきたい。

*3: 正直、無いというと語弊がある。実際は「スーパーノード」と呼ばれる、Skypeを起動している端末たちの中で安定している、いわば「選ばれし端末」が色々と中継点を担っているが、調べながら執筆しているのと、詳しく書くと次のネタが無くなるので、これは次回のおはなし。

*4: 次回の掲載は、来週月曜日6月18日ごろを予定しています。ただ、中の人の状況によって1週間ズレる場合もあります。

ECサイト構築パッケージ「エレコマ」のインストール手順@Ubuntu 10.10

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめまして、よしだです。 DoRuby 初投稿の今回は、最近になって SourceForge.jp から GitHub にこっそり移住したECサイト構築パッケージ「エレコマ」オープンソース版のインストール手順を紹介したい思います。

 概要

通販サイトを作りたい! という要望を簡単に実現してくれる EC サイト構築パッケージ。エレコマは日本初の Ruby on Rails を利用した EC サイト構築パッケージで、オープンソースであるため無料で利用することができます。

詳しい機能については『エレコマ公式サイト』を参照してください。また、実際の動作を確認できるデモサイトもあります。

今回はエレコマのインストール手順を紹介したいと思います。

 環境

OS と DB は基本的には何でも構いません。

ここでは OS に Ubuntu 10.10 を利用することにします。

(ちなみに、CentOS へのインストール手順は GitHub 上の README に書かれています)

  • ◇ OS: Ubuntu 10.10
  • ◇ DB: PostgreSQL
  • ◇ WEB: Apache
  • ◇ APP: Passenger
  • ◇ Ruby: 1.8.7
  • ◇ Ruby on Rails: 2.3.5
  • ◇ RubyGems: 1.3.5

上記が今回用意する環境になります。

 インストール手順

早速インストールしていきます。

ここでは Ubuntu 10.10 がクリーンインストールされていることを前提とします。

0. パッケージリストのアップデート(必ず行ってください!)

手始めに Ubuntu のパッケージリストを最新のものにします。

Ubuntu 10.10 の場合、初期のパッケージリストでは killapache などの脆弱性を取り込むことになってしまいます(killapache については、ととろさんの記事『apache の脆弱性』が詳しいです)。

そこで、各ソフトウェアをインストールする前にパッケージリストの更新を行っておくと安心です。

$ sudo su -
(パスワードを入力し、管理者権限に切り替えます)
# apt-get update

1. Ruby のインストール

Ruby とその他の必要なソフトウェアをインストールします。

特定バージョンの Ruby を利用するためにソースからコンパイルします。

# apt-get -y install gcc zlib1g-dev libssl-dev ncurses-dev libreadline-dev
# wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7-p174.tar.gz
# tar zxf ruby-1.8.7-p174.tar.gz
# cd ruby-1.8.7-p174
# ./configure
# make
# make install
# cd

2. RubyGems のインストール

RubyGems をインストールします。

# wget http://rubyforge.org/frs/download.php/60718/rubygems-1.3.5.tgz
# tar zxf rubygems-1.3.5.tgz
# cd rubygems-1.3.5
# ruby setup.rb
# cd

3. ImageMagick のインストール

エレコマでは商品画像を扱うためのライブラリとして ImageMagick を利用します。

CentOS 向けのインストール手順では ImageMagick へのリンクがすでに切れているようです。

リンクが切れている場合は、適宜 URL を変更して実行してください。

# apt-get -y install libjpeg-dev libpng-dev libgd2-xpm-dev libfreetype6-dev
# apt-get -y install libperl-dev
# wget http://ftp.nl.netbsd.org/pub/pub/ImageMagick/ImageMagick-6.5.8-4.tar.gz
# tar zxf ImageMagick-6.5.8-4.tar.gz
# cd ImageMagick-6.5.8-4
# ./configure
# make
# make install
# cd

4. Rmagick のインストール

Rmagick は ImageMagick を Rails から扱うための Gem です。

# gem install rmagick -v 2.12.2

5. その他の依存 Gem のインストール

エレコマの各機能に必要な Gem をインストールします。

確実な動作を保障するためにバージョンを指定してインストールします。

# gem install rails -v 2.3.5
# gem install gettext -v 2.1.0
# gem install gruff -v 0.3.6
# wget http://www.artonx.org/data/lhalib/lhalib-0.8.1.gem
# gem install lhalib-0.8.1.gem
# gem install webmock -v 1.3.4
# gem install thoughtbot-factory_girl -v 1.2.2 --source http://gems.github.com
# gem install json
# gem install daemons

6. PostgreSQL のインストール

PostgreSQL 本体と Rails 用の Gem をインストールします。

# apt-get -y install postgresql libpq-dev
# gem install postgres

7. ユーザの作成

エレコマを実行するユーザを作成します。

パスワードも適当に設定しておくと良いかもしれません。

# useradd -m ec
# passwd ec
Enter new UNIX password: elephant
Retype new UNIX password: elephant

8. Git のインストール

GitHub からエレコマをダウンロードするにあたって Git が必要になるので、これをインストールします。

# apt-get -y install git-core

9. エレコマのダウンロード

いよいよエレコマのインストールに入ります。

まずは GitHub からエレコマのパッケージをダウンロードします。

# cd /usr/local
# git clone git://github.com/elecoma/elecoma.git
# chown -R ec:ec /usr/local/elecoma

10. PostgreSQL のセットアップ

エレコマ用のデータベースを用意します。

ここでは Development, Test, Production という Rails 環境に合わせて3つのデータベースを作成します。

# /etc/init.d/postgresql start
# su - postgres
postgres$ psql template1
postgres=# alter user postgres with password 'hoge';
(パスワードを適当に設定しておきます)
postgres=# q\
postgres$ createuser ec
Shall the new role be a superuser? (y/n) y
postgres$ psql template1
postgres=# alter user ec with password 'elephant';
(このパスワードは手順 11. で必要になるので覚えておきましょう)
postgres=# \q
postgres$ createdb --owner=ec ec_dev
CREATE DATABASE
postgres$ createdb --owner=ec ec_test
CREATE DATABASE
postgres$ createdb --owner=ec ec
CREATE DATABASE
postgres$ psql -l
        List of databases
   Name    |  Owner   | Encoding 
-----------+----------+----------
 ec        | ec       | UTF8
 ec_dev    | ec       | UTF8
 ec_test   | ec       | UTF8
 postgres  | postgres | UTF8
 template0 | postgres | UTF8
 template1 | postgres | UTF8
(6 rows)

11. エレコマのセットアップ

エレコマを動作させるための最低限の設定を行います。

# su - ec
ec$ cd /usr/local/elecoma/config
ec$ cp database.example.yml database.yml
ec$ vim database.yml
(データベースへのアクセスに必要なユーザ名を ec、パスワードを elephant といった具合に設定します)
ec$ diff database.example.yml database.yml
3,4c3,4
<   username: postgres
<   password: 
---
>   username: ec
>   password: elephant
ec$ cd environments
ec$ vim production.rb
(環境に合わせてメールサーバの設定を変更します)

12. プラグインのインストール

エレコマに必要な Rails プラグインをインストールします。

一部古いバージョンのプラグインを利用するために、変則的なインストール方法を取っているところがあるので注意してください。

ec$ cd /usr/local/elecoma
ec$ ruby script/plugin install git://github.com/realityforge/rails-active-form.git
ec$ ruby script/plugin install git://github.com/rails/acts_as_list.git
ec$ ruby script/plugin install git://github.com/technoweenie/acts_as_paranoid.git
ec$ ruby script/plugin install git://github.com/rails/acts_as_tree.git
ec$ ruby script/plugin install http://topfunky.net/svn/plugins/ar_fixtures/
ec$ ruby script/plugin install git://github.com/jpmobile/jpmobile.git -r 'tag 0.0.8'
ec$ ruby script/plugin install http://taslam-plugins.googlecode.com/svn/trunk/jpmobile_emoticon_filter/
ec$ cd vendor/plugins
ec$ git clone git://github.com/tmtysk/mbmail.git mbmail
ec$ cd mbmail
ec$ git checkout 654ce3ec2dfa10ac3b05cd9354eb84456d206a6d
ec$ rm -fr lib/jpmobile
ec$ rm -fr .git
ec$ cd ../../..
ec$ ruby script/plugin install git://github.com/jamesgolick/resource_controller.git
ec$ cd vendor/plugins/
ec$ git clone  git://github.com/mislav/will_paginate.git
ec$ cd will_paginate/
ec$ git checkout origin/2-3-stable
ec$ cd ../../..
ec$ ruby script/plugin install git://github.com/kakutani/yaml_waml.git
ec$ ruby script/plugin install git://github.com/rails/ssl_requirement.git
ec$ ruby script/plugin install git://github.com/DianthuDia/double_submit_protection.git
ec$ ruby script/plugin install git://github.com/champierre/image_submit_tag_ext.git
ec$ ruby script/plugin install git://github.com/dchelimsky/rspec-rails.git -r 'tag 1.2.9'
ec$ ruby script/plugin install git://github.com/dchelimsky/rspec.git -r 'tag 1.2.9'

13. データベースのセットアップ

データベースにエレコマ用のテーブルとカラムを用意します。

ec$ cd /usr/local/elecoma
ec$ rake db:migrate RAILS_ENV=production

14. Apache2 と Passenger のインストール

今回はウェブサーバに Apache2 を、アプリケーションサーバには Passenger を採用しました。

この他の、たとえば nginx + Unicorn などの組み合わせでも導入は可能です。

# apt-get -y install apache2
# apt-get -y install build-essential libcurl4-openssl-dev
# gem install passenger
# passenger-install-apache2-module

15. Apache2 の設定

アプリケーションサーバとの連携を行うための設定を施します。

バージョンの違いや、エレコマのインストール先ディレクトリによって記述に違いが出るので注意してください。

# cat > /etc/apache2/httpd.conf
LoadModule passenger_module /usr/local/lib/ruby/gems/1.8/gems/passenger-3.0.12/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/1.8/gems/passenger-3.0.12
PassengerRuby /usr/local/bin/ruby

# cat > /etc/apache2/conf.d/ec.conf

  ServerName ec.example.com
  DocumentRoot /usr/local/elecoma/public
  RailsEnv production
  
    AllowOverride all
    Options -MultiViews
  

16. Apache2 の再起動

設定を反映するために Apache2 を再起動します。

もしかしたら reload だけでも良いかもしれませんが試してません。

# /etc/init.d/apache2 restart

 インストール完了

お疲れ様でした!

以上の手順をもって、エレコマのインストールは完了です。

(ブラウザからアクセスすると、エレコマのデモサイトが閲覧できます)

次回はインストール後の初期設定について書きます。

オンラインゲームを有利にしてみよう!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

今回は、オンラインゲームで自分を有利にするチート行為に迫ってみよう

一般的に、チートはゲームをプレイするうえで、自分に有利なように働きかけるパッチやアプリケーションによって行われる。オンラインゲームではないゲームの場合、保存されているセーブデータを書き換えることで、自分のレベルを上げたり、アイテムを増やしたりすることができる。オンラインゲームの場合、そう簡単に行うことはできない。前回説明したように、チートを管理しているゲートウェイが存在しており、送られるパケットの整合性をチェックしており、そう簡単に、通過することはできない。

そもそも、ネットゲーの場合、ユーザのPCにインストールされているアプリは、あくまでもクライアントであり、実際にプレイを行っているのは、接続されたサーバ上になる。このため、どんなにPC上のクライアントを変更しようとも、その過程をチェックしているゲートウェイをだますことができなれば、チート行為は成立しない。

このゲートウェイは、ネットワークセキュリティにおける、IDSやIPSと同等のことを行っていると考えれば良いだろう。通常、やりとりされる通信の内容から、不正を見抜く方法が用いられる。この場合、何らかの方法を用いてチェックサムをチート時も書き換える必要がある。

 では、具体的にその手法についてみていこう。

チート行為を行うには、大きく分けて2種類の方法がある。1つはメモリを書き換える方法だ。先ほど書いたように、ゲームのデータそのものは、サーバ側に蓄積されている従って、これを直接書き換えることはできない。が、ゲームの仕様上、一時的にクライアントアプリのメモリ空間に持つことがある。これは、高速な回線で通信していれば問題ないが、低速な回線(100kbps以下)では、戦闘中のデータを的確に更新することが出来ず、サーバ内での戦闘とユーザの見ている戦闘が同期しないケースが出るためである。クライアントに保持される内容には激しい戦闘情報やアイテム交換など様々な要素が有り、戦闘が始まる前と終わるときに、サーバとクライアント間でデータが交換される。複数のユーザで的を倒す際も、同様の行為が行われるが、この場合はユーザが敵に対して行った攻撃情報がサーバを介して各ユーザに敵の状態と共に提供される。

このような状況で、注目すべきは、クライアントに保持されるメモリの内容だ。

このメモリの内容は、定期的にチェックされ、改ざんできないようにチェックされている。このチェックは、ユーザの目からすると常に行われているように見えるが、リアルタイムで行われているわけではなく、早い状態だと数μs程度、遅くとも数ms程度で行われている。当然として、この速度はゲーム全体の速度からすれば、かなり遅い「割り込み」であり、これ以外にも様々な「割り込み」が存在する。

 今回は、この割り込みについて注目する。

先ほども述べたように、メモリ内の改ざんチェックの割り込みは、ゲーム全体からすると、かなり遅い部類に入る。割り込みタイミングさえわかれば、次の行為を行える。

1.アイテムや経験値、金などが含まれるメモリアエリアを特定する

2.割り込みタイミングを定点観測し、どの時点での割り込みが「もっとも頻繁に行われるか」を確認する

このうち、2.が重要となるので、何度もリトライを繰り返した方が良いだろう。

1は、ゲームによって異なるが、多くの場合は、メモリの相対アドレスは決まっており、そのメモリ内に、確実にアイテムなどの情報はまとまって置かれる。

 やり方はこうだ。

1のエリアを限定した状態で、1の内容を他のエリアに一度コピーする。

2の割り込みが入った直後に、内容を改ざんする。2の割り込みが入る直前に、コピーした元の内容を書き戻す。書き戻す際には、ゲームで進行した情報は忘れずに加える。

こうすることで、メモリ内部は書き換えられ、ゲーム進行は思いのまま、得られる金や経験値、レベルなどはウハウハである。

とはいえ、これを人間業で行うことは、とうてい無理。そこで、プログラムを書くわけだが、イメージ的にはバッファオーバーフローをしかける事に似ている。

メモリを直接書き換える場合は、「割り込み」の存在を必ず忘れないように!

 パケットを改ざんする方法

先ほどは「割り込み」との戦いであったが、今度は、ゲームサーバのチートチェッカとの戦いだ。

チートチェッカは、送られてくるパケットの内容が適切であるかをチェックしている。とはいえ、すべてのパケットの内容を一つ一つ確認しているわけではなく、これも割り込みを利用している。クライアントから送信するパケットを改ざんし、送信すればたちどころに「チート行為」と見抜かれてしまう。では、どのようにするかというと、、、

パケットを改ざんしたら、必ず「チェックサムと呼ばれる物も改ざんする。」チェックサムは、そのパケットが正しいかを確認している物であり、内容(数値上の内容)とそのチェックサムさえ一致すれば、チートチェッカは素通りさせてくれる「可能性がある」。あくまでも、可能性であることを忘れてはならない。

こういった行為は、あまり頻繁にやると、「垢バン」される事になりかねない。十分注意されたい。

安価なVPSを骨の髄までしゃぶり尽くそう!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

最近、安価なVPS(Virtual Private Server)が大量に出回っているのは、読者も知っているだろう。このVPSを使うにあたり、様々な問題が出ていることを知っているだろうか。今回は、そうした、VPSの問題点やセキュリティ上の不備について考えてみたいと思う。

 国内のVPS について

まず、国内のVPS事情についてだ。国内には、様々な事業者がVPSを提供している。中には、月々わずか500円足らずで借りることのできるVPSすら存在する。また、VPSでは足らずに、クラウドサービスを利用しているユーザもいる。これらのVPSでは、ディスク容量やCPUの数、スレッド数、メモリサイズなどで、事細かにサービス品目が異なる。

では、実際にいくつかのサービスについてみてみよう。

まずは、先ほど示したワンコインVPSだ。中で稼働しているOSは、Centos 5.5 だ。このサービスでは、同一サーバ上に、数多くのユーザを利用していると推測され、非常に動作が重いのが特徴だ。そこで、処理能力を計測すべく、下記のようなコマンドを実行してみた。

何はともかく、ディスクへの書き込みが異様に重いと感じる。

time sudo yum update

real 6m15.104s

user 0m5.041s

sys 0m0.683s

同様の環境を、比較的高価な別のVPSに用意し、同じ time sudo yum update を実行した結果は、下記だ。このように、非常に安価なvpsは、サービスレベルに難があるように感じられる。

time sudo yum updat

real 1m23.131s

user 0m33.218s

sys 0m19.095s

 踏み台に対する考え方

さて、お次はこれらのvpsを利用していると、セキュリティ上の問題がどのように発生しているかをみてみよう。

まず、高速かつ、安定したvpsを設置している同一のセグメントから、大量のsshアタックがやってきた。

49.212.2.xxx (www20109u.xxxxx.ne.jp): 6110 times

49.212.47.xxx (www31424u.xxxxx.ne.jp): 59 times

49.212.97.xxx (www39397u.xxxxx.ne.jp): 1576 times

これらは、すべて同一の事業者が提供しているvpsからのssh atackだ。みてわかるとおり、その数たるや尋常な数字ではない。では、こうした攻撃がなぜ発生しているか?それについて、ひもといていこう。

まず、こうしたssh atack は、管理者が適切な管理をしていないから発生していることは言うまでもない。非常に安価であり、大量にドメインを抱えたり、情報を配信したとしても、誰からも文句を言われない。そう、利用者はレンタルサーバ屋である場合がある。その証拠に、ssh atack をしているIPアドレスにアクセスすると、レンタルサーバ屋の画面が表示されることがままある。次に、何も考えずに、単なるファイル置き場として、お気楽に考えている、素人が設置しているケースだ。この場合は、apache がデフォルト画面であることや、ssh へのアカウントログインで、root が有効であったり、デフォルトパスワードがそのまま有効であることからも、素人がお気楽に使っていると推測される。

こうしたことから、同一のネットワークから、ssh atack が繰り返し行われている状況を踏まえると、比較的簡単にサーバが踏まれてる(侵入されている)事が多いことに気づかされる。

これに対し、安価なワンコインVPSでは、外部からのssh atack によって、システム全体が高負荷になることを恐れ、vpsが提供されて間もない頃に、早々に、このssh atack の回避がシステムアップデートによって行われた。通常、sshのポートは、22/tcpであるが、これを異なるポートへアップデートしたのである。

皮肉なことに、システムが不安定、かつ、遅いワンコインが、現状以上に遅く、不安定になることを恐れ、ssh ポートを変更した。これに対し、システムが安定稼働している比較的高価なシステムにおいては、現在もなお、22/tcp で稼働し、同一ネットワークからssh atackの攻撃にさらされている現状がある。

 攻撃に遭わないための対策

では、これらの攻撃に遭わないためには、どうすれば良いのだろうか?

ひとつは、安価なvpsサービスが行ったように、port を変更すればよいように思われる。しかしながら、実際には変更されたportが決まっているのであれば、その決まったportに対して攻撃を行うように変更すれば、同様に攻撃が行われるため、単なるportの変更だけでは、対応のしようがない。そこで、単なるportの変更だけではなく、ssh の鍵交換を設定すれば、仮にport番号がばれようとも、関係なくなる。もし、大量にssh atackを受けて困っているのであれば、こうした鍵交換も一つの方法として、考えてみてはいかがだろうか。

では、こうした動きを、攻撃者視点で考えてみよう。

 攻撃者はこう考えているよ

攻撃者は、特定のvpsサービスにログインできれば、その中の情報を調べる。portの開放状態を調べ、traceroute などのネットワークのコマンドを用いて、ネットワークの状態を調べるだろう。ここから、ネットワークの全体像、少なくともセグメントを見極めることができる。こうして、次に行うのは、ssh の辞書アタックだ。同一セグメントに何台のvpsがあるかはわからないが、しつこく辞書アタックを繰り返して行えば、そのうちの1つや2つ、簡単に侵入できるだろう。当然として、ヒットしたパスワードとIDの組み合わせは、他の同一サービス上の、別セグメントに対しても有効であることが多い。

 まとめ

サーバ毎に管理者IDとパスワードを変更する事は重要なことだ。

快適で安価なvpsはそれだけ、周りに不慣れな管理者が居ることにも繋がる。vpsを借りるなら、相応の管理体制をとり、攻撃者から自分のvpsを確実に守れるようになって欲しい。

第1回 PureMVC入門

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめまして、su10です。Flex向けのフレームワークであるPureMVCについて学んだことを自分なりにまとめて解説していきたいと思います。(2012/5/25更新)

 PureMVCあるある

「うちはPureMVC使ってるから勉強しといてね」

「わかりました」

 数時間後…

「(ネット上にわかりやすい説明ない…「Cairngorm」って何だよ…帰りたいよ…)」

こんなことってよくありますよね。自分の場合は「とりあえずコード読んだらわかるだろう」と思ったらhandleNotificationが一体何なのかわからず、目から汗をかきそうになりました。

 PureMVCの基本

まずはPureMVCとは何か?最初に書きましたが、PureMVCはFlex向けのフレームワークです。Flex向けといってもJavaやC#向けもあるらしいので、これを機会に理解しておけば夢が広がります。そもそも「フレームワークってなに?」という人は「フレームワーク プリン」でググってもらうとして、まずは基礎となるMVCという概念の解説です。

Model、View、Controller

MVCはModel、View、Controllerの頭文字を取ったものです。プログラムの機能をこの3つに分けて書くことでコードがわかりやすくなります。MVCの考え方自体はRailsにもありますね。PureMVCでもこの考え方に基づき、コードを書いていくことになります。それぞれの機能は以下のようになっています。

  • ・Model … サーバとのやり取り、データの管理、ビジネスロジック
  • ・View  … ユーザに見える部分の処理
  • ・Controller … ユーザの入力などに応じてModelの機能を呼び出す

「ビジネスロジック」という単語がわかりにくいですが、要するに「ユーザに見える部分の処理とデータやデータベースの処理の間にある処理」のことです。流れとしては次のようになります。

  1. ユーザが入力を行う(View層が処理)
  2. 入力に応じてModel層の機能呼び出し(Controller層が処理)
  3. データの更新などを行う(Model層が処理)
  4. データを取得して見た目に反映する(View層が処理)

コアアクターとFacade(ファサード)

先ほど「○○層」と表現しましたが、実はPureMVCではクラスとしてModelクラス、Viewクラス、Controllerクラスが用意されていて、これら3つをまとめてコアアクターと呼びます。これらのクラスに先述のような機能をそれぞれ分けて実装していくと考えてください(実際には少し違いますが)。

また、Facadeというクラスが用意されていて、Facadeを通じてコアアクターとやりとりができます。もう少し具体的にいうと、Facadeクラスのインスタンス(もっと正確に言うとFacadeクラスを継承したサブクラスのインスタンス)経由でコアアクターの機能を利用することができます。つまり、実際にはコアアクターの3つのクラスをインスタンス化したり直接どうこうする必要はなく、コアアクターは互いを知らなくても良いのです。コアアクターに直接仕事を頼むのではなく、Facadeを通じて仕事をお願いするのです。こうすることでそれぞれのクラスの結合が疎になり、保守性が高まっています。大事なので何度も書きますが、

コアアクターはFacadeを通じてお互いの機能を利用できるので、お互いについて知っている必要はない

です。

いろいろ書いてきましたが、ここで重大発表です。実はコアアクターは先ほどMVCで述べたような仕事はしていません!(\な、なんだってェー!!/)

実際にMVCで述べたような処理を行うのはProxy、MediatorとView Component、Commandと呼ばれるプログラムたちです。コアアクターの仕事はこれらを自分に登録し、管理することです。もちろん登録はFacade経由で行います。コアアクタークラスの仕事をまとめると、次のようになります。

  • ・Model … Proxyを登録(Facade経由)し、管理する
  • ・View  … Mediatorを登録(Facade経由)し、管理する
  • ・Controller … Commandを登録(Facade経由)し、管理する

また、Proxy、MediatorおよびView Component、Commandの役割は次のようになります。

  • ・Proxy … Modelクラスに登録され、サーバとのやり取り、データの管理、ビジネスロジックを担当
  • ・Mediator … Viewクラスに登録され、View Componentの管理、Notificationの送受信を担当
    • ・View Component … Mediatorに登録され、ユーザの入力の受け取りと見た目の処理を担当
  • ・Command … Controllerクラスに登録され、Notificationに応じてProxyを呼び出す

MediatorがViewクラスに管理されてさらにView Componentを管理しているというややこしい構造になっていますが、これについては次回説明したいと思います。

また、ここで初めて出てきたNotificationはイベントにも似た概念なのですが、これについても次回説明したいと思います。

ちなみに、Proxy、Mediator、View Component、Commandにあたるプログラムは当然たくさん必要になってきますが、それらを管理するコアアクタークラス、つまりModelクラス、Viewクラス、Controllerクラスはそれらを管理する大元の存在なのでインスタンスが一つしか必要ありません。Facadeクラスもです。よってコアアクターとFacade(を継承したクラス)のインスタンスはプログラムにただ一つだけ存在し、利用されます。このような「プログラム中に一つしかインスタンスがない」ことを保証するデザインパターンのことを「シングルトンパターン」といいます。また、私が参考にしたサイト(http://translated.by/you/puremvc-implementation-idioms-and-best-practices/into-ja/ (404 Not Found))では「プログラム中に一つしかインスタンスがない」ことを指して「シングルトン」と呼んでいるので、以降はそのような意味で用いることとします。

それでは次回をお楽しみに。

スマートフォン最適化に便利な【weinre】を使ってみた

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。


お久しぶりのwryyyです。

今流行?のスマートフォン最適化サイトを作る際、

スマートフォン実機でサイトを確認したら、デザインが崩れてる!!!となった場合、
皆様はどうしているでしょうか?

・実機だと、FireFoxのFirebugなんて便利なもの使えないし…

・気合を入れて修正しては確認して…ってのもめんどくせー!!!

ってなった時にはもう大変です。

さて、そんな時にオススメするのが今回ご紹介する

weinre

です!

さて、ではまず【weinre】とは何かから入って行きましょう。

weinreとは、簡単に行ってしまえばスマートフォンで閲覧しているページの
・HTML DOM
・CSS
・Javascript
等をPCから確認できるようにしちゃおうっていうツールです。

では、実際にインストールと使用方法について説明していきます。

※ 私のPC環境がMACのため、MACの手順で記載させて頂きます

1. ダウンロード

まずは https://github.com/phonegap/weinre/archives/master ここから

weinre-jar-1.5.0.zip
(mac OSX 10.6 Snow Leoperd 以上の方は weinre-mac-1.5.0.zip)
をダウンロードします。

※ weinre-mac-1.5.0.zip の中身は weinre をパッケージ化したものが入ってます。

2. 解凍

weinre-jar-1.5.0.zip(weinre-mac-1.5.0.zip) を解凍しましょう。

3. 設定ファイルの作成

自分のユーザのホームディレクトリ配下 「.weinre」というディレクトリを作成し、
.weinre 配下にserver.properties というファイルを作成します。

% pwd
/Users/username
% mkdir .weinre
% vim .weinre/server.properties

.weinre/server.properties の中身は以下のようになります。

% cat .weinre/server.properties
boundHost:    -all-
httpPort:     8081 

※ 設定の詳細は http://phonegap.github.com/weinre/Running.html を御覧ください。

4. 実行

・weinre-jar-1.5.0.zip を解凍した場合

% export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home
% java -jar weinre-jar/weinre.jar --boundHost 192.168.3.181

上記コマンドでweinreが起動されます。

※ weinre-jar を実行するには Java 6.0 が必要なので、
事前にexport してJava のバージョンを変えておく。

・weinre-mac-1.5.0.zipを解凍した場合

解凍したディレクトリに出来ている、weinre をダブルクリック

5. 確認

ブラウザから http://[IPアドレス]:[ポート番号] に接続します。

(アドレスは –boundHost 、ポート番号は server.properties で設定したもの)

すると、weinreのページが閲覧できるはずです。

閲覧できたら、「debug client user interface」のリンクをクリックしておいてください。

リンクを押すとchromeのデベロッパーツールのようなページが出ます。

Targets が none になっているはずです。

次はスマートフォンの操作です。

スマートフォンでブラウザから適当なサイト(https://www.google.co.jp/ とか)にアクセスしてください。

アクセスしたら「bookmarklet url in a textarea」と書かれているテキストフィールド

に入力されているJavaScript をなんとかコピーし、

スマートフォンブラウザのURL入力欄に貼りつけて実行してください。

(事前にスマートフォンで http://[IPアドレス]:[ポート番号] に接続し、テキストフィールドに入力されているJavaScript をコピーしてブックマークに登録しておくと次回からブックマークをクリックするだけで利用できるので便利です!)

貼りつけて実行しましたら、元にアクセスしていたページに戻るはずです。

ここで、さきほどPCでクリックしておいたページを見てみましょう。

Targets が緑色で

「192.168.2.83 [channel: 1200079761 id: anonymous] – https://www.google.co.jp/ 」

と表示され、Clients も緑色で表示されるようになりました!

では、上部タブの Elements をクリックしてみてください。

Chrome のデベロッパーツールのように HTML の DOM が表示されたでしょうか。

Chrome のデベロッパーツールのように、DOM 上にマウスを合わせたら、
なんとスマートフォンの画面もその DOM に当たる部分が薄い灰色っぽく反転します!

これでいろいろテストすることが可能になります。

※ いろいろ試した結果、どうもページ遷移は対応していないようで
ページ遷移する毎に weinre の JavaScript を実行させないとダメないようです。

以上がweinreの解説と実行方法になります!
※ 上記実行手順等はコチラを参考にさせていただきました。

※※ 上記サイトによると、呼び方は 「ワイナリー」 もしくは 「ワイナー」 らしいです。

   weinreを説明しているyoutubeの外人さんは「ウィ…ナー?HAHAHA」って言ってました…

是非、利用して快適なスマートフォン最適化サイト開発をお送りください!

rubyでミリ秒までの時間生成方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

「20120509104004229」、「2012-05-09T10:40:04.229Z」
のようなミリ秒までの時間文字列を時間に変換して、計算をしたいことがあります。
簡単ですが、ミリ秒までの時間オブジェクトの生成方法をご紹介します。■ruby1.8.7では下記の書き方です
>> time = Time.utc(2012, 5, 9, 10, 40, 4, 229*1000)
=> Wed May 09 10:40:04 UTC 2012
>> time.iso8601(3)
=> “2012-05-09T10:40:04.229Z”

>> time  = Time.local(2012, 5, 9, 10, 40, 4, 229*1000)
=> Wed May 09 10:40:04 +0900 2012
>> time.iso8601(3)
=> “2012-05-09T10:40:04.229+09:00”

>> time2  = Time.local(2012, 5, 9, 10, 40, 5, 300*1000)
=> Wed May 09 10:40:05 +0900 2012
>> time2 – time
=> 1.071

■ruby-1.9

ruby-1.9では、「to_r」という文字列を有理数に変換するメソッドも使えます。

ruby-1.9.2-p180 :004 > time = Time.utc(2012, 5, 9, 10, 40, 4, 229*1000)
 => 2012-05-09 10:40:04 UTC
ruby-1.9.2-p180 :005 > time.iso8601(3)
 => “2012-05-09T10:40:04.229Z”
ruby-1.9.2-p180 :006 > time.iso8601(6)
 => “2012-05-09T10:40:04.229000Z”

ruby-1.9.2-p180 :007 > time = Time.utc(2012, 5, 9, 10, 40, “4.229”.to_r)
 => 2012-05-09 10:40:04 UTC
ruby-1.9.2-p180 :008 > time.iso8601(6)
 => “2012-05-09T10:40:04.229000Z”
ruby-1.9.2-p180 :009 > time.iso8601(3)
 => “2012-05-09T10:40:04.229Z”

ちなにみ、ruby1.8.7では、
>> time = Time.utc(2012, 5, 9, 10, 40, “4.229”.to_r)
NoMethodError: undefined method `to_r’ for “4.229”:String
        from (irb):34
        from :0

絶対に笑ってはいけないRSpecの現場24時

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

こんにちは、SHIMADAです。 今日は現場の泥臭いRSpec話を書きます。

新しいフィーチャーを追加するとき、specがなかなか通らない、実装が思い通りに進まない、ということがありますよね。
そんなとき、自分の書いたコードが実際にはどう動いているのか確かめる方法が欲しいです。

一番簡単で広く使われているのはデバッグプリントという手法です。
コードの中に p 変数名 と書くと、specの実行途中にその変数の中身がどうなっているか確認できます。

ここで問題になるのが、specがたくさん書いてあるとデバッグプリントが一杯出てきて肝心の調べたいケースが埋もれてしまうという点です。

ちなみに今携わっているプロジェクトのspecを見てみると、examplesの数が1,000を超えてました。

これが一般的な水準で多いのか少ないのか分かりませんが、ここまできてしまうとデバッグプリントがどかどかっと表示されてあっという間に押し流されてしまうので大変です。

そういう状況でもなんとかしようと編み出した泥臭いテクニックを以下に紹介します。

説明のために簡単なバグ入りのコードと、それを検出するテストを用意しました。

コード


class Calculator
  attr_reader :answer

  def plus(a, b)
    @answer = a + a
  end
end

テスト


describe Calculator do
  subject do
    Calculator.new
  end

  it "1 + 1 = 2" do
    subject.plus(1, 1)
    subject.answer.should == 2
  end

  it "2 + 2 = 4" do
    subject.plus(2, 2)
    subject.answer.should == 4
  end

  it "2 + 3 = 5" do
    subject.plus(2, 3)
    subject.answer.should == 5
  end
end

こんな感じでコードとテストを書いたとします。
バグがあるので “2 + 3 = 5” は成功しません。

Calculator#plusにデバッグプリントを埋め込んで、引数と計算結果を調べてみましょう。


  def plus(a, b)
p :chk1
puts "b = #{b.inspect}"
puts "b = #{b.inspect}"
    @answer = a + a
  end

まず、デバッグ用のコードは通常のコードではないことを強調するために、インデントを無視して行頭から書くようにしています。
こうすることでデバッグが終わってコミットする前に、無駄なコードを消し忘れることを防ぎます。

それから、先頭の p :chk1 は僕が個人的に使っているデバッグ用のマーカーです。
RSpecはピリオドがたくさん出力されます。
デバッグ出力が行の途中から始まると折り返しが読みにくいので、:chk1という目印を使って強制的に改行します。


..........:chk1
a = 1
b = 1
......

当然、いろんなところにデバッグプリントを入れていくときは :chk1, :chk2, :chk3… と数字を増やしていきます。

ところで、このままだと全部のテストケースでデバッグプリントが出力されてしまいます。
できれば、失敗するspecの時だけデバッグプリントを出力したいですね。
そこで、specの側に一時的にこういうものを埋め込みます。


  it "2 + 3 = 5" do
$dbg=true
    subject.plus(2, 3)
$dbg=false
    subject.answer.should == 5
  end

はい。ご覧のとおり $dbg は禁断のグローバル変数です。
グローバルなのでspec内で定義して本番コードの中から参照できます。無敵です。

ちなみにコミットする前に除去する一時的なコードなので、この変数は本来のコードと被らなければどんな名前でも構いません。

使い方は、Cでよくある


#define DEBUG


#ifdef DEBUG

のペアと同じです。


  def plus(a, b)
p :chk1 if $dbg
puts "b = #{b.inspect}" if $dbg
puts "b = #{b.inspect}" if $dbg
    @answer = a + a
  end

これで、調べたいテストケースの時だけデバッグプリントを出力させることができるようになりました。
特定のケースで、どの行でどんな挙動が起こっているか確認できると、デバッグはかなり捗ります。

あとそれから、デバッグプリントだけでは足りなくてどうしてもうまくいかない難しいケースのとき、


debugger if $dbg

としたこともあります。specの実行中この箇所に到達すると、Rubyのデバッガが起動するのでステップ、トレースしながらコードを追いかけてなんとか問題を解決することができました。

最後に、コードのバグがとれてspecが通るようになったらこれらは全部消してきれいにしてからコミットします。

タネを明かせばどうっていうこともない簡単なことですが、なかなか役に立つので今までずっと使っています。みなさんもバグに手こずった時、試してみることをお薦めします。

Android UnitTest

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Androidアプリのテストコードを書いてみました。
今回は画面遷移に関するテストコードです。

事前にunitテストの環境を準備する必要があります。

下記などを参考にさせて頂きました。

http://www.yaunix.com/2011/01/08/android%E3%81%A7%E3%81%AEunittest%E3%81%AE%E5%A7%8B%E3%82%81%E6%96%B9/ (410 Gone)

 Activityコード

public class MainActivity extends Activity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LinearLayout contentView = getContentView();
        setContentView(contentView);
    }
    
    private LinearLayout getContentView() {
        LinearLayout l = new LinearLayout(this);
        Button button = new Button(this);
        button.setText("ターゲットへ遷移するボタン");
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.setClassName(getApplicationContext(), TargetActivity.class.getName());
                startActivity(intent);
            }
        });
        l.addView(button);
        return l;
    }

}

 テストコード

/**
 * 
 * ActivityInstrumentationTestCase2を継承したクラスを作成する 
* テストするクラスを指定する(MainActivity) * */ public class MainActivityTest extends ActivityInstrumentationTestCase2<mainactivity> { /** * 次の画面へ遷移するためのボタン */ private Button button; /** * コンストラクタ * テストするクラスを指定する(MainActivity) */ public MainActivityTest() { super("MainActivityTest",MainActivity.class); } /** * テスト前の準備 */ @Override protected void setUp() throws Exception { super.setUp(); /** * Buttonを取得しておく */ button = (Button) getActivity().findViewById(1); } public void testOnClick() { getActivity().runOnUiThread(new Runnable() { @Override public void run() { /** * 遷移先のクラスをMonitorにセットする */ ActivityMonitor monitor = new ActivityMonitor(TargetActivity.class.getName(), null, true); getInstrumentation().addMonitor(monitor); /** * Buttonをクリックする * (押せることもテストしておく) */ assertTrue(button.performClick()); /** * 画面遷移したあとのクラスを取得する */ Activity next = getInstrumentation().waitForMonitorWithTimeout(monitor, 10); /** * Monitorでセットしたクラスと画面遷移したクラスが同じことを検証する */ assertEquals(monitor.getHits(), 1); if ( next != null ) { /** *遷移した画面を閉じる */ next.finish(); } } }); } }

次は画面遷移以外のテストコードも投稿できればと思ってます。

参考になれば幸いです。

カテゴリで既存メソッドを拡張しようとすると表示されるwarningの対応

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

最近はiPhoneアプリ開発をさせてもらっているのですが、
いつからか(下記参考リンクによるとXcode4.3かららしいですが)、カテゴリを利用して既存クラスの既存メソッドを拡張(上書き)しようとすると


"category is implementing a method which will also be implemented by its primary class"

というwarningメッセージが表示されるようになりました。

やはりwarningメッセージを出しっぱなしだと気持ち悪いので、表示させない方法を調べたところ


#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"

// 拡張したいメソッドを記述

#pragma clang diagnostic pop

と #pragmaで囲むと表示されなくなります。

参考サイト

最近人気な記事