2013年11月27日水曜日

改造版ツイスター

10年以上前に書いたツイスターの改造版が見つかったので掲載します。GPLとかBSDとかのライセンスはよくわからないので、もし、この公開が問題あるようならご指摘くださいm(_ _)m

主な改造内容はコメントを見ていただければわかりますが、オリジナルの実装だと最初に作った乱数を使い果たすとすべてを再度作る様になっています。これでは実使用上、不特定のタイミングで大きなオーバーヘッドが生じることになってしまいます。

そこで乱数を使用するごとに次周の分を作成するようにしました。これにより実運用上は大きなオーバーヘッドの変化が生じないと思います。

Twister.h

#if !defined(AFX_TWISTER_H__7CBE0C01_D79E_11D2_A3E1_00606733955B__INCLUDED_)
#define AFX_TWISTER_H__7CBE0C01_D79E_11D2_A3E1_00606733955B__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

//====================================================================
//====================================================================
//====================================================================
//
// Twister.h: CTwister クラスのインターフェイス
//
//====================================================================
//====================================================================
//====================================================================

class CTwister  
{
    //================================================================
    //=== 構築/消滅 ==================================================
    //================================================================
public:
    CTwister();

    //================================================================
    //=== アトリビュート (定数) ======================================
    //================================================================
protected:
    enum {
        N = 624,                                // データースロット数
        M = 397,                                // インターリブ長
        MATRIX_A   = 0x9908b0df,                // constant vector a
        UPPER_MASK = 0x80000000,                // most significant w-r bits
        LOWER_MASK = 0x7fffffff,                // least significant r bits
    
        TEMPERING_MASK_B = 0x9d2c5680,
        TEMPERING_MASK_C = 0xefc60000,
    };

    //================================================================
    //=== アトリビュート (変数) ======================================
    //================================================================
protected:
    DWORD m_dwlData[N+M];
    int m_iCurPos;

    //================================================================
    //=== アトリビュート (関数) ======================================
    //================================================================
protected:
    DWORD dwGetData( int iIndex )
        { return m_dwlData[(iIndex) % (N+M)]; }

    DWORD dwCreateNew( int iPos );

    DWORD dwTemperingShiftU( DWORD dw )
        { return dw >> 11; }
    DWORD dwTemperingShiftS( DWORD dw )
        { return (dw <<  7) & (DWORD)TEMPERING_MASK_B; }
    DWORD dwTemperingShiftT( DWORD dw )
        { return (dw << 15) & (DWORD)TEMPERING_MASK_C; }
    DWORD dwTemperingShiftL( DWORD dw )
        { return dw >> 18; }

    //================================================================
    //=== オペレーション =============================================
    //================================================================
public:
    void Randomize( DWORD dwSeed = 0 );
    DWORD dwRandom( );

    int iRandom( )
        { return (int)dwRandom( ); }
    WORD wRandom( )
        { return (WORD)dwRandom( ); }

    DWORD dwRandom( DWORD dwLimit );
    int iRandom( int iLimit )
        { return (int)dwRandom( (DWORD)iLimit ); }

protected:
    void SetData( int iIndex, DWORD dwData )
        { m_dwlData[(iIndex) % (N+M)] = dwData; }
};

//====================================================================
//====================================================================
//====================================================================
#endif // !defined(AFX_TWISTER_H__7CBE0C01_D79E_11D2_A3E1_00606733955B__INCLUDED_)
Twister.cpp
//====================================================================
//====================================================================
//====================================================================
//
// Twister.cpp : CTwisterインプリメンテーション ファイル
//
//  元のアルゴリズムでは、一度に全スロットにデーターを設定し、使い終わ
//  ったらまた全スロット再設定するようになっていたが、これでは、処理速
//  度が変化してしまい使いにくいので、1つ使うごとに次週のデーターを作
//  成するように修正しました。
//
//  この修正のためデーターバッファのサイズが2倍になってしまいました。
//
//====================================================================
//====================================================================
//====================================================================

#include "stdafx.h"
#include "Twister.h"

//=== ヘッダー・ファイル・インクルード ===============================

//=== インライン関数インクルード =====================================

//====================================================================
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//====================================================================
//=== tempering parameters ===========================================
//====================================================================

//====================================================================
//=== 構築 ===========================================================
//====================================================================

CTwister::CTwister()
{
    Randomize( 4357/*0*/ );
}

//====================================================================
//=== 新たなデーターの作成 ===========================================
//====================================================================

inline DWORD CTwister::dwCreateNew( int iPos )
{
    DWORD dw0 =  dwGetData( iPos );
    DWORD dw1 =  dwGetData( iPos + 1 );
    DWORD dwM =  dwGetData( iPos + M );

    DWORD dw = (dw0 & (DWORD)UPPER_MASK) | (dw1 & (DWORD)LOWER_MASK);
    dw = dwM ^ (dw >> 1) ^ ((dw & 1) ? MATRIX_A : 0);

    return dw;
}

//====================================================================
//=== 乱数初期化 =====================================================
//====================================================================

void CTwister::Randomize( DWORD dwSeed/* = 0*/ )
{
    if ( dwSeed )
        m_dwlData[0] = dwSeed & 0xffffffff;
    else
        m_dwlData[0] = ::GetTickCount( );

    //================================================================
    for ( m_iCurPos = 1 ; m_iCurPos < N ; ++ m_iCurPos )
        m_dwlData[m_iCurPos] = ( 69069 * m_dwlData[m_iCurPos-1] ) & 0xffffffff;

    //================================================================
    for ( int i = 0 ; i < N ; ++ i )
    {
        DWORD dw = dwCreateNew( i );
        SetData( i, dw );
    }

    //================================================================
    m_iCurPos = 0;
}

//====================================================================
//=== 乱数発生 =======================================================
//====================================================================

DWORD CTwister::dwRandom( )
{
    //================================================================
    //=== 今回の乱数を生成 ===========================================
    //================================================================
    DWORD dwRet = m_dwlData[m_iCurPos];

    //=== +M 位置の作成のため今回の値を保存 ==========================
    SetData( m_iCurPos + N, dwRet );

    //=== 乱数作成 ===================================================
    dwRet ^= dwTemperingShiftU(dwRet);
    dwRet ^= dwTemperingShiftS(dwRet);
    dwRet ^= dwTemperingShiftT(dwRet);
    dwRet ^= dwTemperingShiftL(dwRet);

    //================================================================
    //=== 次周の為のデーターを作成 ===================================
    //================================================================
    DWORD dw = dwCreateNew( m_iCurPos );
    SetData( m_iCurPos + N, dw );

    //================================================================
    //================================================================
    //================================================================
    m_iCurPos = (m_iCurPos + 1) % (N + M);

    //================================================================
    //================================================================
    //================================================================
    return dwRet; 
}

//====================================================================
//=== 引数未満の乱数を発生 ===========================================
//====================================================================

//DWORD CTwister::dwRandom( DWORD dwLimit )
//{
//  return (int)(((__int64)dwRandom() * (__int64)dwLimit) >> 32);
//}
//
#pragma warning(disable : 4035)
DWORD CTwister::dwRandom( DWORD dwLimit )
{
    dwRandom( );
__asm
    {
        MUL     [dwLimit]
        MOV     EAX, EDX
    }
}
#pragma warning(default : 4035)

//====================================================================
//=== オリジナルです =================================================
//====================================================================
//
//DWORD CTwister::dwRandom( )
//{
//  DWORD y;
//  static DWORD mag01[2] = {0x0, MATRIX_A};
//
//  if ( m_iCurPos >= N )
//  {
//      /* generate N words at one time */
//      int kk;
//
//      if ( m_iCurPos == N+1 )   /* if sgenrand() has not been called, */
//          Randomize( 4357 ); /* a default initial seed is used   */
//
//      for (kk=0;kk> 1) ^ mag01[y & 0x1];
//      }
//
//      for (;kk> 1) ^ mag01[y & 0x1];
//      }
//
//      y = (m_dwlData[N-1]&UPPER_MASK) | (m_dwlData[0]&LOWER_MASK);
//      m_dwlData[N-1] = m_dwlData[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
//
//      m_iCurPos = 0;
//  }
//
//  y = m_dwlData[m_iCurPos++];
//  y ^= TEMPERING_SHIFT_U(y);
//  y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
//  y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
//  y ^= TEMPERING_SHIFT_L(y);
//
//  return y; 
//}

2013年1月16日水曜日

1.9.0 で jQuery.browser がエラーになる


管理画面で使用している cleditor が突然動かなくなったとお客様より連絡があり調べたところ、非推奨メソッドの jQuery.browser が使用されていました。

恐らく、jQuery が 1.9.0 にバージョンアップされた際に削除されたものと思われます。

とりあえずの対応としては下記の2通りあるかと思います。

1. jquery-1.8.3.min.js を使う

2. 下記のパッチを当てる
//@@mod  ie = $.browser.msie,
  ie = (typeof($.browser.msie) != 'undefined') ? $.browser.msie : false;

//@@mod  documentClickAssigned,
  documentClickAssigned = false,

2012年12月7日金曜日

IE8 で文字化け

常識かもしれませんが、ちと引っかかったのでメモ。

ヘッダーのメタタグに下記を入れたページを作成しました。

<meta http-equiv="Content-Type" content="text/html; charset=UTF8">

これが IE8 だと見事に文字化けしました><;

Content-Type で文字セットしてしているのになんでだ!?スペルミス?

さっそくグーグル先生に問い合わせてみるとどうやら UTF-8 が正解だったようです。大文字小文字の区別はないようです。

うむむ、ちと恥ずかしいミスでした…

2012年11月14日水曜日

PHP フォームでアップロードできるファイル数の上限

ちょいとハマったので覚書です。

PHP は CentOS 5.7 の標準である 5.1.6 を使用しています。

フォームに <input type="file" /> を30個ほど並べたところ、$_FILES に20個分しか入っていません???

アップロードできるファイル数に制限があったかなぁと調べてみたのですが見当たりません???

ファイルアップロード設定オプション
名前デフォルト変更可能変更履歴
file_uploads"1"PHP_INI_SYSTEMPHP <= 4.2.3 では PHP_INI_ALL、PHP 4.0.3 以降で利用可能
upload_tmp_dirNULLPHP_INI_SYSTEM
max_input_nesting_level64PHP_INI_PERDIRPHP 5.3.9 以降で利用可能。
max_input_vars1000PHP_INI_PERDIRPHP 5.3.9 以降で利用可能。
upload_max_filesize"2M"PHP_INI_PERDIRPHP <= 4.2.3 では PHP_INI_ALL
max_file_uploads20PHP_INI_SYSTEMPHP 5.2.12 以降で利用可能。

上記を見ると 5.2.12 以降では php.ini の設定で変えられるようです。

PHP_INI_SYSTEM となっていますので、httpd.conf のバーチャルホスト設定に下記の1行を追加
php_value max_file_uploads  40

アパッチを再起動してみましたが状況が変わりません。

やっぱ、5.1.6 では実装されていないのかな?と思いましたが諦めきれずに php.ini に直接書いてやりました。

アパッチを再起動すると全部取得できるではないですか!?

max_file_uploads は 5.1.6 でも効果はあるが、php.ini に直接書かなければならないということのようです。

2012年5月11日金曜日

SJIS で HTMLPurifier を使う悩み

ひさしぶりの書き込みです^^;

今回管理画面から設定するメッセージにHTMLを使用できるようにしました。
携帯サイトがあるので文字コードは SJIS です。

管理画面からの入力なので、比較的セキュリティは緩くてもいいかなと思ったのですが、何買ったら心配なので HTML Purifier にて、ヤバいタグや属性を除去するように。

$config = HTMLPurifier_Config::createDefault();
$config->set( 'Core.Encoding', 'SJIS' );
$config->set( 'Core.Language', 'ja' );
$config->set( 'HTML.AllowedElements', $g_aryHTMLPurifierAllowTag );
$objPurifier = new HTMLPurifier( $config );
$str = $objPurifier->purify( $str );

ここで困ったのが © や ® などの HTML 特殊文字です。

フォームからはちゃんと © や ® という形で送られてくるのですが HTML Purifier を通すと消えてなくなっている・・・

で調べてみると、HTML  Purifier は、© や ® を © や ® に変換してしまうことが判明、また、set( 'Core.Encoding', 'SJIS' ); していると SJIS に変換できない文字は消してしまうようです。

とりあえず、© ® を別のキーワード(全角が安全?)に変換してから purify() してその後に戻してやるというヤクザな方法で逃げました^^;

2011年11月4日金曜日

JSON を使って配列の初期化

JSON の使い方のページを見るとオブジェクトの初期化方法を書かれているものが多く、単なるの配列の初期化方法はあまり書かれていません。 備忘録として記しておきます。

 1. 単純な配列を初期化
var a = ["abc", "def"];

2. 連想配列(オブジェクト)を初期化
var a = {"a":"abc", "b":"def"};

2011年10月6日木曜日

PHP HTMLタグの属性をパースする

HTMLタグの属性をパースする関数を作って見ました。
//====================================================================
//! タグの属性をパースする
//! 属性名はアルファベット, 記号(-_), 数字を認めます。
//! 値は "' での括りを認めます。
//! @param string $str タグの属性文字列
//! 例 type=submit type="submit" type='submit' checked
//! @return array キーが属性名の配列
//====================================================================
function aryParseTagAttribute( $str )
{
 //=== 正規表現 ===================================================
// $ma の要素番号
//  1                2 34                  5 67                    8 9
 $re = <<<_EOL_
/\s*([A-Za-z0-9_\-]+)(=(([^"'][^\s]*[^"'])|('(([^'\\\\]|\\\\.)*)')|("(([^"\\\\]|\\\\.)*)")))?/
_EOL_;
 $iMatches = preg_match_all( $re, $str, $ma );

 $aryAttr = array( );
 for ( $i = 0; $i < $iMatches; ++ $i )
 {
  //=== 属性名 =================================================
  $strName = $ma[1][$i];

  //=== 値を取得 ===========================================
  // type="submit"
  // $ma[] は (かっこの順にサブ文字列を格納している
  if ( !empty( $ma[4][$i] ) )
   $strValue = $ma[4][$i]; // 括り無し
  else if ( !empty( $ma[6][$i] ) )
   $strValue = $ma[6][$i]; // '' 括り
  elseif ( !empty( $ma[9][$i] ) )
   $strValue = $ma[9][$i]; // "" 括り
  else
   $strValue = '';   // 値なし

  //============================================================
  $aryAttr[$strName] = $strValue;
 }

 //================================================================
 return $aryAttr;
}

◆テスト
$s = <<<_EOL_
type="text" name='DATE' onclick="func( '\"test\"' ); return" width=100
_EOL_;

$a = aryParseTagAttribute( $s );
print_r( $a );

◆実行結果
Array
(
    [type] => text
    [name] => DATE
    [onclick] => func( '\"test\"' ); return
    [width] => 100
)