CodeIgniterのページングがあまり好きではないので

Paginationクラスを作成してみた。

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * Pagination Class
 *
 * @package     MyNETS2
 * @subpackage  Libraries
 * @category    Pagination
 * @author      KUNIHARU Tsujioka 2009-07-10
 */
class MYNETS_Pagination {

    private $base_url           = ''; // リンクのベースになるURL
    private $total_rows         = ''; // トータルのレコード数
    private $per_page           = 10; // 1ページに表示する最大レコード数
    private $num_links          =  2; // リンクに表示させるページ番号数
    private $cur_page           =  1; // 初期ページ番号
    private $first_link         = '&lsaquo; 最初';
    private $next_link          = '&gt;';
    private $prev_link          = '&lt;';
    private $last_link          = '最後 &rsaquo;';
    private $uri_segment        = 3;  // URLセグメント内のページ番号の場所
    private $full_tag_open      = '';
    private $full_tag_close     = '';
    private $first_tag_open     = '';
    private $first_tag_close    = '&nbsp;';
    private $last_tag_open      = '&nbsp;';
    private $last_tag_close     = '';
    private $cur_tag_open       = '&nbsp;<strong>';  // 現在のページ番号での表示コントロール
    private $cur_tag_close      = '</strong>';
    private $next_tag_open      = '&nbsp;';
    private $next_tag_close     = '&nbsp;';
    private $prev_tag_open      = '&nbsp;';
    private $prev_tag_close     = '';
    private $num_tag_open       = '&nbsp;';
    private $num_tag_close      = '';
    private $page_query_string  = FALSE; // クエリーパラメータでページ番号を渡すかどうか
    private $query_string_segment = 'per_page'; // クエリーパラメータでページ番号を渡す際のパラメータ名

    private $jumpping           = FALSE; // リンク表示でのページをジャンプさせるかスライドさせるか
    private $num_pages          = 1;

    /**
     * Constructor
     *
     * @access  public
     * @param   array   initialization parameters
     */
    function __construct($params = array())
    {
        if (count($params) > 0)
        {
            $this->initialize($params);
        }

        //log_message('debug', "Pagination Class Initialized");
    }

    // --------------------------------------------------------------------

    /**
     * Initialize Preferences
     *
     * @access  public
     * @param   array   initialization parameters
     * @return  void
     */
    function initialize($params = array())
    {
        if (count($params) > 0)
        {
            foreach ($params as $key => $val)
            {
                if (isset($this->$key))
                {
                    $this->$key = $val;
                }
            }
        }
    }

    // --------------------------------------------------------------------

    /**
     * Generate the pagination links
     *
     * @access  public
     * @return  string
     */
    function create_links()
    {
        if ($this->total_rows == 0 OR $this->per_page == 0)
        {
           return '';
        }

        // トータルのページ数
        $this->num_pages = ceil($this->total_rows / $this->per_page);

        if ($this->num_pages == 1)
        {
            return '';
        }

        // セグメントまたはパラメータからページ番号を取得する
        $CI =& get_instance();

        if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
        {
            if ($CI->input->get($this->query_string_segment) != 0)
            {
                $this->cur_page = $CI->input->get($this->query_string_segment);

                $this->cur_page = (int) $this->cur_page;
            }
        }
        else
        {
            if ($CI->uri->segment($this->uri_segment) != 0)
            {
                $this->cur_page = $CI->uri->segment($this->uri_segment);

                $this->cur_page = (int) $this->cur_page;
            }
        }

        $this->num_links = (int)$this->num_links;

        // セグメントまたはパラメータのページ番号が数字じゃない場合は0ページとする
        if ( ! is_numeric($this->cur_page) OR $this->cur_page == 0)
        {
            $this->cur_page = 1;
        }

        // トータルレコード数より現在のページ番号が大きい場合
        // セグメントの値をページ番号にする
        if ($this->cur_page > $this->num_pages)
        {
            $this->cur_page = $this->num_pages;
        }

        // base url の生成
        if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
        {
            $this->base_url = rtrim($this->base_url).'&amp;'.$this->query_string_segment.'=';
        }
        else
        {
            $this->base_url = rtrim($this->base_url, '/') .'/';
        }

        $output = '';

        // 表示ページ数が0の場合、次へ、前へのみのリンクとする
        // 携帯の場合に使う?
        if ($this->num_links < 1)
        {
            // 最初へのリンクを生成
            $output .= $this->_start_link();

            // 前へのリンクを生成
            $output .= $this->_prev_link();

            // 次へのリンクを生成
            $output .= $this->_next_link();

            // 最後へのリンクを生成
            $output .= $this->_last_link();
        }
        else
        {
            //最初のリンク
            $output .= $this->_start_link();

            // 前へのリンクを生成
            $output .= $this->_prev_link();

            // ページ番号リンクの生成
            $output .= $this->_generate_page_link();

            // 次へのリンクを生成
            $output .= $this->_next_link();

            // 最期のリンクを作成
            $output .= $this->_last_link();
        }

        $output = preg_replace("#([^:])//+#", "\\1/", $output);

        $output = $this->full_tag_open.$output.$this->full_tag_close;

        return $output;
    }

    // 最初のリンクを生成
    private function _start_link()
    {
        if  ($this->cur_page > $this->num_links)
        {
            return $this->first_tag_open
                  .'<a href="'.$this->base_url.'">'.$this->first_link.'</a>'
                  .$this->first_tag_close;
        }
        return '';
    }

    // 最後のリンクを生成
    private function _last_link()
    {
        if (($this->cur_page + $this->num_links) < $this->num_pages)
        {
            return $this->last_tag_open
                  .'<a href="'.$this->base_url.$this->num_pages.'">'.$this->last_link.'</a>'
                  .$this->last_tag_close;
        }
        return '';
    }

    // 前へのリンクを生成
    private function _prev_link()
    {
        if  ($this->cur_page > 1)
        {
            $i = $this->cur_page - 1;
            if ($i == 0) $i = '';
            return $this->prev_tag_open
                  .'<a href="'.$this->base_url.$i.'">'.$this->prev_link.'</a>'
                  .$this->prev_tag_close;
        }
        return '';
    }

    // 次へのリンクを生成
    private function _next_link()
    {
        $tag = '';
        if ($this->cur_page < $this->num_pages)
        {
            $i = $this->cur_page + 1;
            $tag = $this->next_tag_open
                  .'<a href="'.$this->base_url.$i.'">'.$this->next_link.'</a>'
                  .$this->next_tag_close;
        }
        return $tag;
    }

    // ページ番号リンク生成時の最初の頁番号
    private function _start_page()
    {
        /*if ($this->jumpping)
        {
        }
        else
        {*/
            if (($this->cur_page - $this->num_links) > 0)
            {
                return $this->cur_page - $this->num_links;
            }
            else
            {
                return 1;
            }
        /*}*/
    }

    // ページ番号リンク生成時の最後の頁番号
    private function _end_page()
    {
        /*if ($this->jumpping)
        {

        }
        else
        {*/
            if (($this->cur_page + $this->num_links) < $this->num_pages)
            {
                return $this->cur_page + $this->num_links;
            }
            else
            {
                return $this->num_pages;
            }
        /*}*/
    }

    private function _generate_page_link()
    {
        $start = $this->_start_page();
        $end   = $this->_end_page();
        $tag   = '';

        // ページ番号リンクの生成
        for ($loop = $start; $loop <= $end; $loop++)
        {
            if ($this->cur_page == $loop)
            {
                // 現在のページの生成
                $tag .= $this->cur_tag_open.$loop.$this->cur_tag_close;
            }
            else
            {
                $tag .= $this->num_tag_open
                         . '<a href="'.$this->base_url.$loop.'">'.$loop.'</a>'
                         . $this->num_tag_close;
            }
        }
        return $tag;
    }
}
// END MYNETS_Pagination Class

/* End of file MYNETS_Pagination.php */
/* Location: ./system/mynets/libraries/MYNETS_Pagination.php */

あまりちがいはないですが、CIのページネーションと同じよびだしかた、パラメータで動きます。
ひとつ違うところは、携帯の場合ページ番号を並べるリンクだと、へたしたら数百ページの場合
たいへんなことになるので、
表示するページの前後をいくつにするか、
$num_links
を0にしたら、エラーで戻すのではなく、次へ、前へ、のみを表示し、ページ番号のリンクを生成しないようにしました。

TO DO
JUMP表示を取り入れる。PEARにはあったと思いますが、表示固定でそのページを超えるまではリンクは変わらないってやつです。
いらないかなw
携帯向けに、ページ総数、総レコード数などを見えるようにする、現在のページ番号を取得で来るようにする、というのは入れたいな。

URLENCODEでのちょっとしたこと

CodeIgniterでURLの文字に日本語などを扱う場合、URL文字列の指定を変更しますが、
PHPでurlencodeをかけた場合、空白が+に置き換わります。

urlencode()

これだと、URLに+が通るようにCodeIgniterのconfigを変えないといけないのですが、
rawurlencode()を使うと対応可能となりました。

メモ

{CodeIgniter]CodeIgniterでファイルアップした時の重複したファイル名がいけてない。

CIでファイルアップを使った方はご存じだと思いますが、同じファイルを連続でアップした場合
ファイル名に自動的に数字が付与されていきます。

例)
hogehoge111.jpg
を3回アップすると
hogehoge1112.jpg
hogehoge1113.jpg
という感じでアップされていきます。これはちょっとアレゲな感じ。
で、これを
hogehoge111_2.jpg
という形にするためのハック。

uploadクラスの
set_filename()メソッドをいじります。

そのメソッドの中に

for ($i = 1; $i < 100; $i++)
{
}

があります。
この中に
if ( ! file_exists($path.$filename.$i.$this->file_ext[$this->field]))
の判定がありますが、これを改造。
if ( ! file_exists($path.$filename.'_'.$i.$this->file_ext[$this->field]))
として、$iの前に'_'を連結します。
※なお、MYNETSのuploadクラスは、複数ファイルアップに対応したために、$this->file_ext[$this->field]と最後に連結していますが、
通常はこうじゃありませんが、$iのあたりは全く同じです。

で、その判定の下に
$new_filename = $filename.$i.$this->file_ext[$this->field];
があるので、これを
$new_filename = $filename.'_'.$i.$this->file_ext[$this->field];とすると、
アンダースコアで区切られたファイル名が出来上がります。

CodeIgniterでのイメージ操作処理について

かなりご無沙汰なブログですが。
先日、CIでのファイルのアップの変更をかきましたが、WEBサイトでファイルアップで一番多いのが、なんと言っても画像関係だと思います。
CIでは、image_libという画像操作のライブラリがありますが、簡単なメソッドしかありません。

たとえば、リサイズ。

resize()メソッドがあるのですが、WIDTHとHEIGHT両方を指定しないと、デフォルトのファイルの幅になります。
しかし、実際に多いのは、
180X180ピクセルの幅に収まるようにすることが多いんじゃないでしょうか。
この場合、強制的に180X180で指定してしまうと、正方形の画像ならいいですが、まずそんなことはありません。

つまり、縦横、どちらかが180ピクセルに収まるように最適化する必要があるということです。

で、そんなあなたに(自分ですが)便利なヘルパーを作ってみました。

MYNETS_file_helper.phpとして、アプリケーションのhelpersディレクトリに保存します。
あ、通常はMYNETS_ではなく、MY_ですね。

かなり強制的なヘルパーにしているので、最適化する部分のコードのみ。

        $s_width  = $img_data['image_width'];
        $s_height = $img_data['image_height'];
        $w = PROFILE_IMAGE_WIDTH;
        $h = PROFILE_IMAGE_HEIGTH;
        
        if (!$w) $w = $s_width;
        if (!$h) $h = $s_height;

        // リサイズの必要がない場合
        if ($s_width <= $w && $s_height <= $h)
        {
            //そのまま
            $img_conf['width']  = $s_width;
            $img_conf['height'] = $s_height;
        }
        else
        {
            // 出力サイズ変更
            $o_width  = $s_width;
            $o_height = $s_height;

            if ($w < $s_width)
            {
                $o_width  = $w;
                $o_height = $s_height * $w / $s_width;
                if ( $o_height < 1 )
                {
                    $o_height = 1;
                }
            }
            if ($h < $o_height && $h < $s_height)
            {
                $o_width  = $s_width * $h / $s_height;
                $o_height = $h;
                if ( $o_width < 1 )
                {
                    $o_width = 1;
                }
            }
            
            $img_conf['width']  = $o_width;
            $img_conf['height'] = $o_height;
        }

PROFILE_IMAGE_WIDTH等の定数には、プロフィール用画像の最適ピクセルサイズを入れておきます。
$image_dataは、投稿されたファイルのデータです。
CIのuploadクラスを使った場合、
$image_data = $CI->upload->data('image_file');
こんな感じで取得できるはずです。

開設すると、もとファイルのサイズと、最適化したいサイズを用意し、
比較。
その後、楯が180なのか横が180で最適化されるのかを判断して、$img_conf配列に入れています。
で、その後に
$CI->load->library('image_lib', $img_conf);
$CI->image_lib->resize();
これで最適化された縦横180ピクセルに収まります。

{CodeIgniter]CodeIgniterで複数のファイルをアップする

CodeIgniterのUplodクラスは、どうも一つのファイルのアップを想定しているようです。

でやってみました。

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 *
 * @category
 * @package    Upload Class
 * @author     KUNIHARU Tsujioka <kunitsuji@gmail.com>
 * @copyright  Copyright (c) 2008 KUNIHARU Tsujioka <kunitsuji@gmail.com>
 * @copyright  Copyright (c) 2006-2008 Usagi Project (URL:http://usagi-project.org)
 * @license    New BSD License
 */

class MYNETS_Upload extends CI_Upload {

    var $file_temp      = array();
    var $file_name      = array();
    var $orig_name      = array();
    var $file_type      = array();
    var $file_size      = array();
    var $file_ext       = array();
    ///////////////////////////////
    var $field          = 'userfile';
    ///////////////////////////////
    /**
     * Constructor
     *
     * @access  public
     */
    function __construct($props = array())
    {
        parent::__construct();
        if (count($props) > 0)
        {
            $this->initialize($props);
        }

        log_message('debug', "Upload Class Initialized");
    }

    // --------------------------------------------------------------------
    //2009/01/21 KUNIHARU Tsujioka add
    function is_uploaded($field)
    {
        if ( ! is_uploaded_file($_FILES[$field]['tmp_name']))
        {
            return FALSE;
        }
        else
        {
            return TRUE;
        }
    }

    //2009/01/21 KUNIHARU Tsujioka add
    function set_field_name($field)
    {
        $this->field = $field;
    }
    /**
     * Perform the file upload
     *
     * @access  public
     * @return  bool
     */
    //2009/01/21 KUNIHARU Tsujioka UPDATE
    function do_upload($field = '')
    {
        //$this->is_uploaded[$this->field] = FALSE;

        if ($field)
        {
            $this->field = $field;
        }
        // Is $_FILES[$this->field] set? If not, no reason to continue.
        if ( ! isset($_FILES[$this->field]))
        {
            $this->set_error('upload_no_file_selected');
            return FALSE;
        }

        // Is the upload path valid?
        if ( ! $this->validate_upload_path())
        {
            // errors will already be set by validate_upload_path() so just return FALSE
            return FALSE;
        }

        // Was the file able to be uploaded? If not, determine the reason why.
        if ( ! is_uploaded_file($_FILES[$this->field]['tmp_name']))
        {
            $error = ( ! isset($_FILES[$this->field]['error'])) ? 4 : $_FILES[$this->field]['error'];

            switch($error)
            {
                case 1: // UPLOAD_ERR_INI_SIZE
                    $this->set_error('upload_file_exceeds_limit');
                    break;
                case 2: // UPLOAD_ERR_FORM_SIZE
                    $this->set_error('upload_file_exceeds_form_limit');
                    break;
                case 3: // UPLOAD_ERR_PARTIAL
                   $this->set_error('upload_file_partial');
                    break;
                case 4: // UPLOAD_ERR_NO_FILE
                   $this->set_error('upload_no_file_selected');
                    break;
                case 6: // UPLOAD_ERR_NO_TMP_DIR
                    $this->set_error('upload_no_temp_directory');
                    break;
                case 7: // UPLOAD_ERR_CANT_WRITE
                    $this->set_error('upload_unable_to_write_file');
                    break;
                case 8: // UPLOAD_ERR_EXTENSION
                    $this->set_error('upload_stopped_by_extension');
                    break;
                default :   $this->set_error('upload_no_file_selected');
                    break;
            }

            return FALSE;
        }

        // Set the uploaded data as class variables
        $this->file_temp[$this->field] = $_FILES[$this->field]['tmp_name'];
        $this->file_name[$this->field] = $this->_prep_filename($_FILES[$this->field]['name']);
        $this->file_size[$this->field] = $_FILES[$this->field]['size'];
        $this->file_type[$this->field] = preg_replace("/^(.+?);.*$/", "\\1", $_FILES[$this->field]['type']);
        $this->file_type[$this->field] = strtolower($this->file_type[$this->field]);
        $this->file_ext[$this->field]    = $this->get_extension($_FILES[$this->field]['name']);

        // Convert the file size to kilobytes
        if ($this->file_size[$this->field] > 0)
        {
            $this->file_size[$this->field] = round($this->file_size[$this->field]/1024, 2);
        }

        // Is the file type allowed to be uploaded?
        if ( ! $this->is_allowed_filetype())
        {
            $this->set_error('upload_invalid_filetype');
            return FALSE;
        }

        // Is the file size within the allowed maximum?
        if ( ! $this->is_allowed_filesize())
        {
            $this->set_error('upload_invalid_filesize');
            return FALSE;
        }

        // Are the image dimensions within the allowed size?
        // Note: This can fail if the server has an open_basdir restriction.
        if ( ! $this->is_allowed_dimensions())
        {
            $this->set_error('upload_invalid_dimensions');
            return FALSE;
        }


        // Sanitize the file name for security
        $this->file_name[$this->field] = $this->clean_file_name($this->file_name[$this->field]);

        // Truncate the file name if it's too long
        if ($this->max_filename > 0)
        {
            $this->file_name[$this->field] = $this->limit_filename_length($this->file_name[$this->field], $this->max_filename);
        }

        // Remove white spaces in the name
        if ($this->remove_spaces == TRUE)
        {
            $this->file_name[$this->field] = preg_replace("/\s+/", "_", $this->file_name[$this->field]);
        }

        /*
         * Validate the file name
         * This function appends an number onto the end of
         * the file if one with the same name already exists.
         * If it returns false there was a problem.
         */
        $this->orig_name[$this->field] = $this->file_name[$this->field];

        if ($this->overwrite == FALSE)
        {
            $this->file_name[$this->field] = $this->set_filename($this->upload_path, $this->file_name[$this->field]);

            if ($this->file_name[$this->field] === FALSE)
            {
                return FALSE;
            }
        }

        /*
         * Move the file to the final destination
         * To deal with different server configurations
         * we'll attempt to use copy() first.  If that fails
         * we'll use move_uploaded_file().  One of the two should
         * reliably work in most environments
         */
        if ( ! @copy($this->file_temp[$this->field], $this->upload_path.$this->file_name[$this->field]))
        {
            if ( ! @move_uploaded_file($this->file_temp[$this->field], $this->upload_path.$this->file_name[$this->field]))
            {
                 $this->set_error('upload_destination_error');
                 return FALSE;
            }
        }

        /*
         * Run the file through the XSS hacking filter
         * This helps prevent malicious code from being
         * embedded within a file.  Scripts can easily
         * be disguised as images or other file types.
         */
        if ($this->xss_clean == TRUE)
        {
            $this->do_xss_clean();
        }

        /*
         * Set the finalized image dimensions
         * This sets the image width/height (assuming the
         * file was an image).  We use this information
         * in the "data" function.
         */
        $this->set_image_properties($this->upload_path.$this->file_name[$this->field]);

        return TRUE;
    }

    // --------------------------------------------------------------------

    /**
     * Finalized Data Array
     *
     * Returns an associative array containing all of the information
     * related to the upload, allowing the developer easy access in one array.
     *
     * @access  public
     * @return  array
     */
    //2009/01/21 KUNIHARU Tsujioka UPDATE
    function data($filed = 'uploadfile')
    {
        return array (
                        'file_name'         => $this->file_name[$this->field],
                        'file_type'         => $this->file_type[$this->field],
                        'file_path'         => $this->upload_path,
                        'full_path'         => $this->upload_path.$this->file_name[$this->field],
                        'raw_name'          => str_replace($this->file_ext[$this->field], '', $this->file_name[$this->field]),
                        'orig_name'         => $this->orig_name[$this->field],
                        'file_ext'          => $this->file_ext[$this->field],
                        'file_size'         => $this->file_size[$this->field],
                        'is_image'          => $this->is_image(),
                        'image_width'       => $this->image_width,
                        'image_height'      => $this->image_height,
                        'image_type'        => $this->image_type,
                        'image_size_str'    => $this->image_size_str,
                    );
    }


    // --------------------------------------------------------------------

    /**
     * Set the file name
     *
     * This function takes a filename/path as input and looks for the
     * existence of a file with the same name. If found, it will append a
     * number to the end of the filename to avoid overwriting a pre-existing file.
     *
     * @access  public
     * @param   string
     * @param   string
     * @return  string
     */
    //2009/01/21 KUNIHARU Tsujioka UPDATE
    function set_filename($path, $filename)
    {
        if ($this->encrypt_name == TRUE)
        {
            mt_srand();
            $filename = md5(uniqid(mt_rand())).$this->file_ext[$this->field];
        }

        if ( ! file_exists($path.$filename))
        {
            return $filename;
        }

        $filename = str_replace($this->file_ext[$this->field], '', $filename);

        $new_filename = '';
        for ($i = 1; $i < 100; $i++)
        {
            if ( ! file_exists($path.$filename.$i.$this->file_ext[$this->field]))
            {
                $new_filename = $filename.$i.$this->file_ext[$this->field];
                break;
            }
        }

        if ($new_filename == '')
        {
            $this->set_error('upload_bad_filename');
            return FALSE;
        }
        else
        {
            return $new_filename;
        }
    }

    // --------------------------------------------------------------------

    /**
     * Validate the image
     *
     * @access  public
     * @return  bool
     */
    //2009/01/21 KUNIHARU Tsujioka UPDATE
    function is_image()
    {
        // IE will sometimes return odd mime-types during upload, so here we just standardize all
        // jpegs or pngs to the same file type.

        $png_mimes  = array('image/x-png');
        $jpeg_mimes = array('image/jpg', 'image/jpe', 'image/jpeg', 'image/pjpeg');

        if (in_array($this->file_type[$this->field], $png_mimes))
        {
            $this->file_type[$this->field] = 'image/png';
        }

        if (in_array($this->file_type[$this->field], $jpeg_mimes))
        {
            $this->file_type[$this->field] = 'image/jpeg';
        }

        $img_mimes = array(
                            'image/gif',
                            'image/jpeg',
                            'image/png',
                           );

        return (in_array($this->file_type[$this->field], $img_mimes, TRUE)) ? TRUE : FALSE;
    }

    // --------------------------------------------------------------------

    /**
     * Verify that the filetype is allowed
     *
     * @access  public
     * @return  bool
     */
    //2009/01/21 KUNIHARU Tsujioka UPDATE
    function is_allowed_filetype()
    {
        if (count($this->allowed_types) == 0 OR ! is_array($this->allowed_types))
        {
            $this->set_error('upload_no_file_types');
            return FALSE;
        }

        foreach ($this->allowed_types as $val)
        {
            $mime = $this->mimes_types(strtolower($val));

            if (is_array($mime))
            {
                if (in_array($this->file_type[$this->field], $mime, TRUE))
                {
                    return TRUE;
                }
            }
            else
            {
                if ($mime == $this->file_type[$this->field])
                {
                    return TRUE;
                }
            }
        }

        return FALSE;
    }

    // --------------------------------------------------------------------

    /**
     * Verify that the file is within the allowed size
     *
     * @access  public
     * @return  bool
     */
    //2009/01/21 KUNIHARU Tsujioka UPDATE
    function is_allowed_filesize()
    {
        if ($this->max_size != 0  AND  $this->file_size[$this->field] > $this->max_size)
        {
            return FALSE;
        }
        else
        {
            return TRUE;
        }
    }

    // --------------------------------------------------------------------

    /**
     * Verify that the image is within the allowed width/height
     *
     * @access  public
     * @return  bool
     */
    //2009/01/21 KUNIHARU Tsujioka UPDATE
    function is_allowed_dimensions()
    {
        if ( ! $this->is_image())
        {
            return TRUE;
        }

        if (function_exists('getimagesize'))
        {
            $D = @getimagesize($this->file_temp[$this->field]);

            if ($this->max_width > 0 AND $D['0'] > $this->max_width)
            {
                return FALSE;
            }

            if ($this->max_height > 0 AND $D['1'] > $this->max_height)
            {
                return FALSE;
            }

            return TRUE;
        }

        return TRUE;
    }

    // --------------------------------------------------------------------

    /**
     * Runs the file through the XSS clean function
     *
     * This prevents people from embedding malicious code in their files.
     * I'm not sure that it won't negatively affect certain files in unexpected ways,
     * but so far I haven't found that it causes trouble.
     *
     * @access  public
     * @return  void
     */
    //2009/01/21 KUNIHARU Tsujioka UPDATE
    function do_xss_clean()
    {
        $file = $this->upload_path.$this->file_name[$this->field];

        if (filesize($file) == 0)
        {
            return FALSE;
        }

        if (($data = @file_get_contents($file)) === FALSE)
        {
            return FALSE;
        }

        if ( ! $fp = @fopen($file, FOPEN_READ_WRITE))
        {
            return FALSE;
        }

        $CI =& get_instance();
        $data = $CI->input->xss_clean($data);

        flock($fp, LOCK_EX);
        fwrite($fp, $data);
        flock($fp, LOCK_UN);
        fclose($fp);
    }

    // --------------------------------------------------------------------

}
// END Upload Class

/* End of file Upload.php */
/* Location: ./systemmynets/libraries/MYNETS_Upload.php */

とりあえず、アップロードする回数だけチェックする必要はりますが。

久しぶりにCodeIgniterの内容

ソースを書こうかと思ったのですが、かなり多い。。。ので、概要のみ。
もう少ししたらSVNで見れるようになるので、その時に評価したい人はお願いします。

CodeIgniterでモバイルとPCを同じ用に管理し、セッションまで行う方法として。

まず、既出のmobileidクラス。これは、ユーザーエージェントを見て、EZ番号やらドコモのi-modeid等を取得するクラス。
これを使って、セッションクラスを用意しました。

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 *
 * @category
 * @package    Session Class
 * @author     KUNIHARU Tsujioka <kunitsuji@gmail.com>
 * @copyright  Copyright (c) 2008 KUNIHARU Tsujioka <kunitsuji@gmail.com>
 * @copyright  Copyright (c) 2006-2008 Usagi Project (URL:http://usagi-project.org)
 * @license    New BSD License
 */

// ------------------------------------------------------------------------

class Session {

    public $CI;

    public $session_obj  = NULL;

    public $session_type = 'CI';

    private $_params = array();

    /**
     * Session Constructor
     *
     * The constructor runs the session routines automatically
     * whenever the class is instantiated.
     */
    function __construct($params = array())
    {
        //どのセッションを使うかを判定する
        $this->CI = &get_instance();
        $this->session_type = MYNETS_SESSION_TYPE;
        if ($params)
        {
            $this->_params = $params;
        }
        //session_objプロパティにオブジェクトをセットする
        $this->_run();
        //print_r($this->session_obj);
        //exit;
    }

    private function _run()
    {
        //接続端末を判定する
        if ($this->CI->mobileid->is_mobile())
        {
            //ドコモ以外をクッキーにするかどうか
            if (DOCOMO_ONLY_COOKIES == TRUE)
            {
                switch ($this->CI->mobileid->get_carrier())
                {
                    case 'docomo':
                        if ($this->session_type == 'CI')
                        {
                            require_once APPPATH . 'libraries/session/mobile_ci_session.php';
                            $this->session_obj = new mobile_ci_session($this->_params);
                        }
                        else if ($this->session_type == 'PHP')
                        {
                            require_once APPPATH . 'libraries/session/php_session.php';
                            $this->session_obj = new php_session($this->_params);
                        }
                        break;
                    default:
                        require_once APPPATH . 'libraries/session/MYNETS_Session.php';
                        $this->session_obj = new MYNETS_Session($this->_params);
                        break;
                }
            }
            else        //すべてクッキーを使わない
            {
                if ($this->session_type == 'CI')
                {
                    require_once APPPATH . 'libraries/session/mobile_ci_session.php';
                    $this->session_obj = new mobile_ci_session($this->_params);
                }
                else
                {
                    require_once APPPATH . 'libraries/session/php_session.php';
                    $this->session_obj = new php_session($this->_params);
                }
            }
        }
        else
        {
            if ($this->session_type == 'PHP')
            {
                require_once APPPATH . 'libraries/session/php_session.php';
                $this->session_obj = new php_session($this->_params);
            }
            else
            {
                require_once APPPATH . 'libraries/session/MYNETS_Session.php';
                $this->session_obj = new MYNETS_Session($this->_params);
            }
        }
    }

    // --------------------------------------------------------------------

    public function __call($func, $args)
    {
        if (method_exists($this->session_obj, $func))
        {
            return call_user_func_array(array($this->session_obj, $func), $args);
        }
        else
        {
            show_error($func . " method not exists.");
        }

    }

    public function __set($func, $args)
    {
        if (property_exists($this->session_obj, $func))
        {
            $this->session_obj->$func = $args;
        }
        else
        {
            show_error($func . " property not exists.");
        }

    }

    public function __get($func)
    {
        if (property_exists($this->session_obj, $func))
        {
            return $this->session_obj->$func;
        }
        else
        {
            show_error($func . " property not exists.");
        }
    }
}
// END Session Class wrapper

こんな感じでラッパーを用意してみました。
で、application/libraryの下に
session/ディレクトリを用意。そこにそれぞれの処理ファイルを置いておきますです。

利用方法としては、
携帯で利用するかPCで利用しているかを判別。
PCで利用している場合、configでCIのセッションを利用するのかPHPセッションを利用するかを判定。
PHPセッションを使う場合はDBを使わずセッションファイルを使います。
CIのセッションを使う場合は、変数はDBに保存されます(Ver1.7.0以降なので)
次に、携帯の場合。
DOCOMO_ONLY_COOKIES
ドコモ以外はクッキーを使うかどうか。(定数名おかしいなぁ)
AUソフトバンクはCIのセッションを使います。
携帯は全部クッキーを使わない場合
CIセッションを使うか、PHPセッションを使うかを判断します。

携帯でCIのセッションを使っても、CIで作成されるセッションIDとDBを使って行います。
ただし、携帯でCIセッションをつかってクッキーを使わない場合、自動的に
URLパラメータにCIのセッションIDが付与されてそれを取得してデータを管理します。

そのために、FORMのOPENやアンカータグのヘルパーもカスタマイズ。
モバイルの場合CIのセッションIDを取得するようになっています。

これで、接続端末を意識しないでヘルパーを使うことでPCでもモバイルでもセッション管理可能となりました。