世界中の共有動画を横断検索。youku.com,youtube,tudou.com,Dailymotionに対応。・・・そんなサービスの開発者ブログ。

みんなの動画サーチ

個人メニュー
最近見た動画

サービス:みんなの動画サーチ   利用できる動画共有サイト : youku.com , youtube , tudou.com , Dailymotion

Skype用の通話録音ツールがあるそうです

 Skypeは無料で使える多機能音声ツールです。便利なのでよく使うのですが、その録音ツールがありました。こちらです。

Tapur

まだ試していませんが、これは良いツールである気がします。
Skypeで会議をやったときに議事録が欲しいなあ、と思っていたので後で使ってみます。
2008-02-29(Fri)

php:ついつい忘れるセキュリティ対応:stripslashes

 入力値のサニタイズはWEBアプリを作るときには必須の作業です。
 WEBアプリはユーザーが限られるクライアント・サーバータイプのアプリケーションと違って、悪意をもったユーザーも入力ができてしまいます。そのため、うっかり入力値チェックを忘れると、テーブルの中身を消されたり、ファイルを破壊されてしまったりする恐れがでてきます。


 ・・・と、なぜ急にこんな基本的なことを書いたかと申しますと、
うっかり共有動画サーチを作るときにサニタイズを忘れていたからです。


 キャッシュファイルを作成するときのファイルパスが下記のような決め方だったのですが

$_GET["入力値"],".cash"

これだと入力値にスラッシュ等の想定していない文字(例:「../」)が入った時に予期せぬ挙動を起こしてしまいます。

 そのため、stripslashes()でサニタイズをかけたものを使うようにしました。


 いやー、危なかったです。セキュリティ対策漏れは気をつけないとすぐ起こしてしまいますね(汗
2008-02-27(Wed)

引数が長すぎます:rm -rf では消せないほどたまったキャッシュの消し方

 私は普段linuxでファイルを一度に削除するときはrm -rfを使うのですが、キャッシュを大量に生成するなどして相当数ファイルが貯まっていると、rm -rfでは「引数が長すぎます」と怒られてファイルが消せないことがあります。

 そういうときはコマンドにひと工夫して xargs を使っています。

【例】
find /var/www/html/movie-search/cache/ -name "*.cash" -print0 | xargs -0 rm -rf

 これで問題なく消せます。

続きを読む

2008-02-25(Mon)

PEARのXML_UnserializerでXMLがうまく読み込めない時があるときは

 XMLをパースしてくれるXML_Unserializerなのですが、本日パースした結果がうまく取得できず、PEAR_ERRORが表示されるという現象に出会いました。

 PEARからのエラーメッセージを見てみると、

No unserialized data available. Use XML_Unserializer::unserialize() first.

 と表示されているのですが、unserialize()ならすでに使っているので、そういうことではなく、別の原因であるようです。

 ではその別の原因とは何か、Googleでそれっぽいキーワードで検索をかけて探っていくと、想定していない文字コードがXMLの中にあるためではないかという仮定を得られました。

 そこで、XMLのテキストデータを渡す前にひと工夫。mb_convert_encoding()を使ってUTF-8に強制的に変換することにしました。
 こんな感じです。

$Xml = mb_convert_encoding($Xml, "UTF-8", "auto");

$unserializer = & new XML_Unserializer();
$unserializer->setOption('parseAttributes',true);
$unserializer->unserialize($Xml);
$result = $unserializer->getUnserializedData();

 結果、うまく通るようになりました。
2008-02-23(Sat)

DNSによる名前解決が遅い! ということでCentos6のIPv6を止めてみたが・・・

 現在半分くらい完成している共有動画サーチなのですが、どういうわけか今日の夜間2100頃、繋がらないことが間断的に発生しました。
 繋がらないのではサービス提供どころではないので、急きょ原因を探りました。が、回線の帯域幅もサーバーのリソースも余裕はあるはずですし(なにしろ現在ユーザーが私一人ですから)、コードにも特に問題はないように思えました。

 これ如何に、と首をひねったのですが、DNSによる名前解決が遅いのを繋がらないと勘違いしたのではないかと思いいたりました。
 以前IPV6が動いているとDNSによる名前解決が遅くなってしまったことがあるので、今回もそれではないかと思ったのです。ブラウザの動作もそれっぽい感じですので、もっとも怪しい原因でした。というわけで、もともと使っていないことでもありますし、IPV6を止めました。


vi /etc/modprobe.conf

#下記2行を追加
alias net-pf-10 off
alias ipv6 off


vi /etc/sysconfig/network

#下記の行のとおりに。(yesからnoに変更)
NETWORKING_IPV6=no


#ついでにIPV6版IPTABLESも停止。
service ip6tables stop
chkconfig ip6tables off


#OSを再起動
shutdown -r now


 結果・・・やはり同じ現象が発生しました。どうも違ったようです。

 そこでルーターが怪しいのだろうかということで、自動になっていたMTUを1454固定にし、ファームウェアも最新のものにバージョンアップしてみました。

 その後、同じ現象は今のところ起こっていません。

 とりあえずこのまま様子を見ることにします。


*あいまいな付記
 事例はFirefoxだと発生せずIEでばかり発生しました。これが偶然でなかったなら、クライアント側に原因があることになります。
2008-02-22(Fri)

windowsにLAMPをインストール

 近頃自分のパソコンがどうにも動きが遅くなっていたので、いろんなソフトをインストールしすぎたためであろうと考え、思い切って再インストールしました。

 その結果開発環境のLAMP(いえ、ただしくはWAMPですが)も再インストールの運びとなりました。
 たいていインストーラに従っておこなえば済むものなのですが、今回は少々苦労しました。

 まずAPACHEのhttpd.conf。

 どういうわけか強制終了になってしまうので、どういうわけかと思ってみてみたら、phpが持つ各バージョンに合わせたのDLLをすべて読んでいました。それは誤作動も起ころうというものです。

 次にphp.ini。
 これもなぜかモジュールをうまく読まず、
Unable to load dynamic library ほにゃらら
 と表示されます。こんな感じですね。
Unable to load dynamic library 'C:\\PHP\\ext\\php_mysql.dll'
 DLLが格納してあるextension_dirも間違っていませんし、書式に特にミスもみあたらず、困り果てていたのですが、とあるサイトで「パスが入っていなかったがためにこのエラーが出た」旨を見てひらめきました。

 インストールしてから再起動してなかったのです。ということは、更新されたパスも読んでいないということになります。

 というわけで再起動してみたら、あっけなく動作しました。

 ちょっとしたところに落とし穴があるものです。
2008-02-21(Thu)

MVCモデルに沿った簡単な自作フレームワーク

私がよく利用するのはPHPなのですが、いかに簡単な言語と言われるPHPとはいえそれなりの規模の開発を行うときはフレームワークがないと不便が多いです。
そんなわけで以前はやったMOJAVIによく似た自作のフレームワークを使っているのですが、今回はその基本となる部分をご紹介します。レンダリングエンジンはSmartyです。


class Controller {

//コンストラクタ。
function Controller()
{
}

function Execute($module_name=DEFMODULE,$action_name=DEFACTION)
{
/*
* 判定のためも兼ねてGET,POSTのデータを取得し統合。重複する場合はPOSTのデータが優先。
*/
$Data=array_merge($_GET,$_POST); //GETのデータにPOSTを追加。GETとPOSTの両方に同じキーの変数がある場合、POST優先。
if (get_magic_quotes_gpc()) $Data=stripslashes_deep($Data);

/*
* module,actionを念のためサニタイズしつつ指定。無いならデフォルト値を入力。
*/
$Data['module'] = isset($Data['module']) ? basename($Data['module']) : $module_name;
$Data['action'] = isset($Data['action']) ? basename($Data['action']) : $action_name;
$module_name = $Data['module'];
$action_name = $Data['action'];


/*
* モジュールの場所の指定
*/
$ModuleDir=MODULE_DIR.$module_name.'/';

//モジュールはここで無いと決まらないのでConfigに置けない
define('MODULE_CLASS_DIR',$ModuleDir."class/");


/*
* モジュール共通の事前処理があるならばそれを実行
* ファイルの有無で処理の有無を判断する。
* 1モジュールに対して1フィルタ。
* クラス名はprefileterのみ。
*/
$FilterFileName=$ModuleDir.'filter/premodule.php';
if(is_file($FilterFileName)){
require $FilterFileName;
$Filter = new premodule;
$Filter->setVal($Data); //GETPOSTのデータ
$Filter->Execute();
}


/*
*モデル(Action)の実行
*/
$ActionFileName=$ModuleDir."actions/".$action_name.".php";
if(is_file($ActionFileName)){
require $ActionFileName;
$Action = new $action_name;
$Action->setVal($Filter->Vals,$Data); //PreのデータとGETPOSTのデータ
$Action->Execute(); //指定Action実行。
}else{
$error="Error 該当ページなし [".$module_name."]:[".$action_name."]";
trigger_error($error, E_USER_ERROR);
}
/*
*ビュークラスの宣言&実行。ただしテンプレートの指定が無い場合は実行せず。
*/
if(!empty($Action->tpl)){
$View = new View(new Renderer_Smarty); //このnew Renderer_Smartyを変えるとレンダリングエンジンを変更できる。そのレンダリングエンジン操作クラスを追加実装する必要はあるが。
$View->display($Action->tpl,$Action->Vals,$module_name);
}
}
}

function stripslashes_deep($value)
{
$value = is_array($value) ?
array_map('stripslashes_deep', $value) :
stripslashes($value);

return $value;
}

class Filter {
var $GPVal;
var $Vals;

//コンストラクタ
function Filter()
{
}

function setVal($GPVal)
{
$this->GPVal=$GPVal;
}

//ここはオーバーライドするところ。
function Execute()
{
}

function sendVal($Key,$Val)
{
$this->Vals[$Key] = $Val;
}
}

class Action {
var $Vals;
var $PreVal;
var $GPVal;
var $tpl;
var $Validator;

//コンストラクタ
function Action()
{
}

function setVal(&$PreVal,&$GPVal)
{
$this->PreVal=$PreVal;
$this->GPVal=$GPVal;

$this->Vals["module"] = $GPVal["module"];
$this->Vals["action"] = $GPVal["action"];

}

function Execute()
{
$Val=$this->GPVal["module"].":".$this->GPVal["Action"]."はオーバーライドが済んでいません";
$this->designateTpl('test.tpl');
}

function sendVal($Key,$Val)
{
$this->Vals[$Key] = $Val;
}

function designateTpl($tpl)
{
$this->tpl = $tpl; //もっともこの指定が無い場合はコントローラがViewが起動させないので重要。
}

function startToken()
{
if(!session_id()) session_start();
$_SESSION["OneTimeToken"] = sha1(session_id().mt_rand().microtime()); //セッションIDを絡めたランダムな文字列。
$this->sendVal("OneTimeToken",$_SESSION["OneTimeToken"]); //TPL側での対応も必要なことに注意されたし。
}

function finishToken()
{
if(!session_id()) session_start();
if($this->GPVal["OneTimeToken"] == $_SESSION["OneTimeToken"]){ //ここが認証。
unset($_SESSION["OneTimeToken"]); //ここがミソ
return true;
}else{
return false;
}
}

function callOther_Action($ActionName,$ModuleName="")
{
if(!class_exists($ActionName)){
if(empty($ModuleName)){
$ModuleName=$this->GPVal["module"]."/";
}
$ModuleDir=MODULE_DIR.$ModuleName.'/';
$ActionFileName=$ModuleDir."actions/".$ActionName.".php";
require $ActionFileName;
}

return new $ActionName;
}

function Validate($GPVal="")
{
//どうしてもオリジナルでかけないといけないものはこんな感じで。
//if($int==15){
// $this->errormessage="15だから駄目";
// return false
//}
return $this->execformalValidate($GPVal);
}

//普段はここをいじる。
function & setValidate($GPVal=""){
$Validator = new Validator();
//$Validator->setRule_Numeric($this->int);//例
return $Validator;
}

//ここはいじらないでも済むように。
function execformalValidate($GPVal=""){
$this->Validator = $this->setValidate($GPVal);
$Iterator = $this->Validator->Iterator(); //Iteratorの取得。
$Check=true;
while(list($key,$Rule)=$Iterator->hasnext()){ //each()を使うのでlistで受けている。
//なんか密度高いなー。Iteratorにした意味が無い気がしてきた。
if($Rule->checkRule()){
unset($this->Validator->Message[$key]);
}else{
$Check=false;
}
}
return $Check;
}

function redirect($URL)
{
if(NOWTESTING==1){
print get_class($this)."にて[ $URL ]へリダイレクトがかかりました
";
return;
}

redirect($URL);
}

}

class View {
var $Renderer;
function View($Renderer)
{
$this->Renderer = $Renderer;
}

//レンダリングクラスに表示させるだけ。
function display($templatename,&$RetData,$module_name)
{
$this->Renderer->setConfig($module_name);
$this->Renderer->display($templatename,$RetData);
}
}

class Renderer_Smarty {
var $Smarty;
function setConfig($module=DEFMODULE) //初期設定。Smartyの宣言と設定だけを行う。configの定数群をちゃんとしないとエラーになる。
{
require_once(SMARTY_DIR.'Smarty.class.php');

//モジュールごとにフォルダを作らないと別のModuleに同名のActionがあったときにキャッシュが誤動作を引き起こす。
if(!is_dir(SMARTY_DATA_DIR.$module."/")) mkdir (SMARTY_DATA_DIR.$module."/");
if(!is_dir(SMARTY_DATA_DIR.$module."/templates_c/")) mkdir (SMARTY_DATA_DIR.$module."/templates_c/");
#chmod(SMARTY_DATA_DIR.$module."/templates_c/", 0777);
if(!is_dir(SMARTY_DATA_DIR.$module."/configs/")) mkdir (SMARTY_DATA_DIR.$module."/configs/");
#chmod(SMARTY_DATA_DIR.$module."/configs/", 0777);
if(!is_dir(SMARTY_DATA_DIR.$module."/cache/")) mkdir (SMARTY_DATA_DIR.$module."/cache/");
#chmod(SMARTY_DATA_DIR.$module."/cache/",0777);

$this->Smarty = new Smarty;
$this->Smarty->register_modifier("make_links_blank", "make_links_blank");
$this->Smarty->register_modifier("number_format","number_format");
$this->Smarty->template_dir = MODULE_DIR.$module."/templates/";
$this->Smarty->compile_dir = SMARTY_DATA_DIR.$module.'/templates_c/';
$this->Smarty->config_dir = SMARTY_DATA_DIR.$module.'/configs/';
$this->Smarty->cache_dir = SMARTY_DATA_DIR.$module.'/cache/';
$this->Smarty->clear_compiled_tpl(); //キャッシュの誤動作が有る場合はここを動作させる。
}

//HTMLだけを返す。
function & fetch($templatename,&$RetData)
{
if(empty($templatename)) return false;
if(is_array($RetData)){
foreach($RetData as $key => $value){
$this->Smarty->assign($key,$value);
}
}

$Html = $this->Smarty->fetch($templatename);

return $Html;
}

//fetchで取ったデータをprintで表示するだけ。
function display($templatename,&$RetData)
{
print $this->fetch($templatename,$RetData);
}

}
2008-02-16(Sat)

AtermWR8500NとAtermWL54SE2で無線LAN

【背景】
月初に小規模オフィスの無線LAN敷設を請け負ったときのメモを、何かに使えるかも知れないので残してみます。

【メモ】
・安定性を重視するとNECのルーターがベストっぽいです。今回はAtermWR8500NとAtermWL54SE2を選択しました。

・同じ無線LAN対応でもメーカーが異なると接続できなかったりするようです。実際NECの親機とSonyの内蔵無線LAN子機では接続できませんでした。Wi-Fiタイプだと比較的安心だそうですが、油断は禁物。必ずメーカーは統一したほうがよさそうです。

・利用するのはUSBタイプのものが手軽なのですが(AtermWL54SU2など)、マシンパワーを食う上に電波が届かない可能性があり、障害時の切り分けも比較的面倒(マシンパワー等マシン本体の問題なのか、電波等機器の問題なのかの切り分けが難しい)という問題があり、トラブルのもとになりがちだそうです。
デスクトップ型の本体を無線LANにつなげたいイーサネットコンバータ タイプがよさそうです。

・PCカードタイプは、ノート型の場合はこれがベスト。ただし電波状態が悪いとだめなので置き場所を選ぶ必要はあります。また、WL300SCなどwindows 2000以上のOSでなければ利用できないものがあるのでOSのバージョンは要チェック。

・子機(イーサネットコンバータ)はAtermWL54SE2、親機はAtermWR8500Nが今のところオススメっぽいです。(*2008年2月時点で)
※家庭用ではありますが、接続する無線LAN端末(子機)は10台以下を推奨、ということなので、まあ小規模LANレベルなら平気でしょう。

・11aのほうが通信の安定面では強く、11b/gはほかの電波とかぶるためちょっと安定性に難があるらしい。デフォルトでは11b/gになっていますが、問題あるようなら11aの規格を利用した方がよいかも。


・ノートパソコンはPCカードがあるからいいとして、デスクトップパソコンはイーサーネットコンバーターまでは結局有線となります。無線LANといってもLANケーブルはやっぱり使うわけですね。
デスクトップはノートと違ってあまり動かさないので、LANケーブルがそれほど邪魔にはならないですが。


・セキュリティ
野良APと呼ばれるような、誰からでもつなげられてしまう無線LANは甚だ困りますので、しっかりセキュリティはかけておきます。とりあえず意識して行ったのはこの3つ。

→MACアドレスフィルタリング
→SSIDの利用
→通信の暗号化(AES)
2008-02-14(Thu)

MYSQLにACCESSでODBC接続

【背景】
管理画面をWEBで作るとどうしても入力インターフェイスが弱くなって嫌なので、Accessでwindowsベースの管理画面を作成することにしました。Accessは少々能力が低い反面とても手軽に管理画面が作成できるので、自分用のちょっとしたDB関連ツールを作るのにはむいています。
ただし、そのままではMysqlにAccessから接続することはできないので、ODBCで接続するためのMYSQL Connector/ODBCをwindows のクライアントにインストールします。

【インストールメモ】
ACCESSでMYSQLを操作したいのでODBCを入れます。10分もあれば設定できるくらい簡単です。数年前、接続できずに(どころか、接続したとたんにMYSQLがダウンするという奇怪な現象に)四苦八苦したのは昔の話です。

ダウンロードはこちらから行います。
MySQL Connectors Downloads


Windows MSI Installer を選んでDL、あとは指示に従ってインストール。


終わり。


・・・と思っていたら、文字コードで苦しみました。
この手の作業にありがちな文字化けです。

結局のところ、ODBC接続設定の、Initial Statement に[SET NAMES SJIS]と入れることで解決しました。これでINSERTもUPDATEもSELECTもUTFでいけます。
なぜSET NAMES UTF8ではなくSET NAMES SJISなのかわかりませんが、ODBCの設定とDBの設定はまた別ものということなのでしょう。
2008-02-12(Tue)

Centos5のサーバーをひとつ用意する

【背景など】
共有動画サーチを始めることにしたので、まずはサーバを用意することに。ちょうど良く空いているサーバーがあったので、それを使うことにしました。
OSのインストール自体は済ませていたので早速APACHEやMYSQL,PHPの設定を行いました。

というわけで、その設定のメモ書きです。

【設定メモ】
*yumを早くする方法
rpm --import http://ftp.riken.jp/Linux/caos/centos/RPM-GPG-KEY-CentOS-5

vi /etc/yum.repos.d/CentOS-Base.repo

コメントアウトされているbaseurl=ほにゃらら部分の下にこう入れる。

baseurl=http://ftp.riken.jp/Linux/centos/$releasever/updates/$basearch/

これをやらないと、bpsが8kbなんてひどい数字がでるから要注意。


*LAMPのインストール

yum install mysql*

vi /etc/my.cnf
以下を追加
/**************
[mysqld]
default-character-set = utf8

[mysql]
default-character-set = utf8
**************/


起動
/etc/rc.d/init.d/mysqld start

自動起動の設定
chkconfig mysqld on
chkconfig --list mysqld


パスワードの設定
mysql -u root
でログインして
set password for root@localhost=password('mysql');

どのIPからでも接続できるようにするにはこれも必要。
GRANT ALL ON *.* TO root@"%" IDENTIFIED BY "mysql";


次、apache
yum install httpd*

APACHEはすぐ開始せずに、まずはphpをインストール。
yum install php*

終わったらアパッチを開始。
/etc/init.d/httpd start

自動起動の設定。
chkconfig httpd on
chkconfig --list httpd


YUMやRPMでのインストールの場合、デフォのドキュメントルートはここになります。
cd /var/www/html

httpd.confはここ。ドキュメントルートの変更やバーチャルホスト、mod_rewriteの設定がしたいときなどはこれを。
/etc/httpd/conf/httpd.conf
2008-02-12(Tue)

 みんなの動画サーチ 現在の人気動画

RSSフィード
最近の記事
月別アーカイブ
カテゴリー
逆アクセスランキング
プロフィール

Author:ナカタツ
 共有動画サーチの開発をやっているフリーランサーです。プログラム歴は趣味で使っていた頃も合わせるとちょうど今年で10年目。最近はPHPばかり使ってます。
 私に興味を持ってくださる方はお気軽にご連絡ください。Skypeでお話できる人歓迎。メールフォームはこちら

カレンダー
01 | 2008/02 | 03
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 -

みんなの動画サーチへ戻る

カテゴリ:芸能・テレビ | 音楽 | アニメ | おもしろ | 神・衝撃 | ゲーム | 動物 | スポーツ | 時事ニュース | 自然・歴史 | 車・バイク | セクシー


アクセス解析 アクセスランキング
  • seo

Powered by FC2 Blog

ホームページ アフィリエイト レンタルサーバー FC2ブログ

Copyright © みんなの動画サーチ開発者ブログ All Rights Reserved.