<?php  /// Moodle Configuration File 

require_once('fs_renderer.php');

function fs_defaultindex() {
    global $fsCFG;
    return $fsCFG->defaultindex;
}

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

// キャラクタセットの設定値を正規化
    if (isset($fsCFG->fsCharset)) {
        $fsCFG->fsCharset    = strtoupper(trim($fsCFG->fsCharset));
    } else {
        $fsCFG->fsCharset = false;
    }
    if (isset($fsCFG->oldfsCharset)) {
        $fsCFG->oldfsCharset = strtoupper(trim($fsCFG->oldfsCharset));
    } else {
        $fsCFG->oldfsCharset = false;
    }

//  // current_charset()関数を利用は止めた．
//------------------------------------------------------------------------

    // カレント文字セットからファイルシステムの文字セットに変換する
    function currentCharset2fsCharset($str)
    {
        return convert2fsCharset($str, 'UTF-8', false);
    }

    // カレント文字セットから旧ファイルシステムの文字セットに変換する
    function currentCharset2oldfsCharset($str)
    {
        return convert2fsCharset($str, 'UTF-8', true);
    }

    // 指定した文字セットからファイルシステムの文字セットに変換する
    function convert2fsCharset($str, $from, $oldfs = false)
    {
        global $fsCFG;

        if (is_fs_sjis($oldfs)) {
            // to S-JIS
            return mb_convert_encoding($str,'SJIS-WIN', $from);
        } else if (is_fs_rawurl($oldfs)) {
            // to 擬似rawurlencode
//          return fs_rawurlencode($str);
            return special_rawurlencode($str);  // (2008/04/16)
        } else if (is_fs_windows($oldfs)) {
            // to localewincharset
            return mb_convert_encoding($str, $fsCFG->fswincharset, $from);
        } else if (is_fs_utf8($oldfs)) {
            // to UTF-8
//          return mb_convert_encoding($str, 'UTF-8', $from);
            return $str;    // UTF-8 → UTF-8は不要 (2008/05/29)
        } else if (is_fs_utf16($oldfs)) {
            // to UTF-16
            return mb_convert_encoding($str, 'UTF-16', $from);
        } else if (is_fs_eucjp($oldfs)) {
            // to EUC-JP
            return mb_convert_encoding($str, 'EUC-JP', $from);
        } else return $str;
    }

    // ファイルシステムの文字セットからカレント文字セットに変換する
    function fsCharset2currentCharset($str)
    {
        return convertFromfsCharset($str, 'UTF-8', false);
    }

    // 旧ファイルシステムの文字セットからカレント文字セットに変換する
    function oldfsCharset2currentCharset($str)
    {
        return convertFromfsCharset($str, 'UTF-8', true);
    }

    // ファイルシステムの文字セットから指定した文字セットに変換する
    function convertFromfsCharset($str, $to, $oldfs = false)
    {
        global $fsCFG;

        if (is_fs_sjis($oldfs)) {
            // from S-JIS
            return mb_convert_encoding($str, $to, 'SJIS-WIN');
        } else if (is_fs_rawurl($oldfs)) {
            // from 擬似rawurlencode
            return mb_convert_encoding(rawurldecode($str), $to);
        } else if (is_fs_windows($oldfs)) {
            // from localewincharset
            return mb_convert_encoding($str, $to, $fsCFG->fswincharset);
        } else if (is_fs_utf8($oldfs)) {
            // from UTF-8
            return mb_convert_encoding($str, $to, 'UTF-8');
        } else if (is_fs_utf16($oldfs)) {
            // from UTF-16
            return mb_convert_encoding($str, $to, 'UTF-16');
        } else if (is_fs_eucjp($oldfs)) {
            // from EUC-JP
            return mb_convert_encoding($str, $to, 'EUC-JP');
        } else return $str;
    }


// arrayの全要素を変換する
// fsCharset2currentCharset_array(array)
    function fsCharset2currentCharset_array($fsArray)
    {
        $cArray = array();
        foreach ($fsArray as $key => $parts) {
            if (is_array($parts)) $cArray[$key] = fsCharset2currentCharset_array($parts);
              else {
                if (is_string($parts)) $cArray[$key] = fsCharset2currentCharset($parts);
                  else $cArray[$key] = $parts;
            }
        }
        return $cArray;
    }

// ------------------------------------------
// ファイルシステムの文字コードチェック
// ------------------------------------------
// ファイルシステムの文字コードがS-JISか？
    function is_fs_sjis($oldfs = false)
    {
        global $fsCFG;

        $canditate = array('S-JIS', 'SJIS', 'SHIFT-JIS','CP932', 'SJIS-WIN');
        if ($oldfs && isset($fsCFG->oldfsCharset)) return in_array($fsCFG->oldfsCharset, $canditate);
            else if (isset($fsCFG->fsCharset)) return in_array($fsCFG->fsCharset, $canditate);
        return false;
    }

// ファイルシステムの文字コードがWindowsか？
    function is_fs_windows($oldfs = false)
    {
        global $fsCFG;

        $canditate = array('WINDOWS', 'WIN');
        if ($oldfs && isset($fsCFG->oldfsCharset)) return in_array($fsCFG->oldfsCharset, $canditate);
            else if (isset($fsCFG->fsCharset)) return in_array($fsCFG->fsCharset, $canditate);
        return false;
    }

// ファイルシステムの文字コードがUTF-8か？
    function is_fs_utf8($oldfs = false)
    {
        global $fsCFG;

        $canditate = array('UTF-8', 'UTF8');
        if ($oldfs && isset($fsCFG->oldfsCharset)) return in_array($fsCFG->oldfsCharset, $canditate);
            else if (isset($fsCFG->fsCharset)) return in_array($fsCFG->fsCharset, $canditate);
        return false;
    }

// ファイルシステムの文字コードがUTF-16か？
    function is_fs_utf16($oldfs = false)
    {
        global $fsCFG;

        $canditate = array('UTF-16', 'UTF16');
        if ($oldfs && isset($fsCFG->oldfsCharset)) return in_array($fsCFG->oldfsCharset, $canditate);
            else if (isset($fsCFG->fsCharset)) return in_array($fsCFG->fsCharset, $canditate);
        return false;
    }

// ファイルシステムの文字コードが擬似URLエンコードか？
    function is_fs_rawurl($oldfs = false)
    {
        global $fsCFG;

        $canditate = array('RAWURL', 'RAWURLENCODE');
        if ($oldfs && isset($fsCFG->oldfsCharset)) return in_array($fsCFG->oldfsCharset, $canditate);
            else if (isset($fsCFG->fsCharset)) return in_array($fsCFG->fsCharset, $canditate);
        return false;
    }

// ファイルシステムの文字コードがEUC-JPか？
    function is_fs_eucjp($oldfs = false)
    {
        global $fsCFG;

        $canditate = array('EUC-JP', 'EUCJP');
        if ($oldfs && isset($fsCFG->oldfsCharset)) return in_array($fsCFG->oldfsCharset, $canditate);
            else if (isset($fsCFG->fsCharset)) return in_array($fsCFG->fsCharset, $canditate);
        return false;
    }

// --------------------------------------------------------------------------
// 日本語フォルダ名／ファイル名を利用する上で独自に開発あるいは拡張した関数群
// --------------------------------------------------------------------------

// PHPにはフォルダごとコピーするコマンドは無いのかな？
// $from：ファイル名あるいはフォルダ名
// $dest：コピー先のフォルダ名（パスの最後の/は無し)
// 擬似RAWURLの場合，フルパス名が非常に長くなる．この場合，複写に失敗してしまう．
    function fs_copy_all($from, $dest)
    {
        $dest = preg_replace('/[\/|\\\]$/', '', $dest);
        // コピー先のフォルダが存在しない場合はエラー
        if (!fs_is_dir($dest)) return false;
        $path_parts = fs_pathinfo($from);
        $dest .= '/'.$path_parts['basename'];
        // 再起呼び出し：コピー元がファイルの場合は終了
        if (fs_is_file($from)) {
            if (!fs_copy($from, $dest)) return false;
            return true;
        } else if (fs_is_dir($from)) {
            if (!fs_mkdir($dest)) return false;
            $dirhandle = fs_opendir($from);
            while (false !== ($subfile = fs_readdir($dirhandle))) {
                if (($subfile == '.') || ($subfile == '..')) continue;
                if (!fs_copy_all("$from/$subfile", $dest)) {
                    closedir($dirhandle);
                    return false;
                }
            }
            closedir($dirhandle);
            return true;
        }
        return false;
    }

// 指定されたフォルダ内のフォルダ名／ファイル名を指定した文字コードに変換（rename)
// フォルダ名をファイル名よりも先にSJISに変更すると問題がある場合も考えられるので，再帰的に変換しながら階層を上がる
    function fs_convertCharset_all($target, $charset)
    {
        $target = preg_replace('/[\/|\\\]$/', '', $target);
        // 再起呼び出し：ファイルならば変換して終了
        if (fs_is_file($target)) {
            $path_parts = fs_pathinfo($target);
            $fsname = currentCharset2fsCharset($target);
            $sjname = currentCharset2fsCharset($path_parts['dirname']).'/'.convertFromfsCharset($path_parts['basename'], $charset);
            if (!rename($fsname, $sjname)) {
                return false;
            }
            return true;
        }
        if (!fs_is_dir($target)) return false;
        $dirhandle = fs_opendir($target);
        while (false !== ($subfile = fs_readdir($dirhandle))) {
            if (($subfile == '.') || ($subfile == '..')) continue;
            if (!fs_convertCharset_all($target.'/'.$subfile, $charset)) {
                closedir($dirhandle);
                return false;
            }
            if (fs_is_dir($target.'/'.$subfile)) {
                $fsname = currentCharset2fsCharset($target.'/'.$subfile);
                $sjname = currentCharset2fsCharset($target).'/'.convertFromfsCharset($subfile, $charset);
                if (!rename($fsname, $sjname)) {
                    closedir($dirhandle);
                    return false;
                }
            }
        }
        closedir($dirhandle);
        return true;
    }

// copy from lib/filelib.php
/**
 * Recursively delete the file or folder with path $location. That is,
 * if it is a file delete it. If it is a folder, delete all its content
 * then delete it. If $location does not exist to start, that is not
 * considered an error.
 *
 * @param $location the path to remove.
 */
    function original_fulldelete($location) {
        if (is_dir($location)) {
            $currdir = opendir($location);
            while (false !== ($file = readdir($currdir))) {
                if ($file <> ".." && $file <> ".") {
                    $fullfile = $location."/".$file;
                    if (is_dir($fullfile)) {
//                      if (!fulldelete($fullfile)) {           // (FS_CONVERTER)
                        if (!original_fulldelete($fullfile)) {  // (FS_CONVERTER)
                            closedir($currdir);
                            return false;
                        }
                    } else {
                        if (!unlink($fullfile)) {
                            closedir($currdir);
                            return false;
                        }
                    }
                }
            }
            closedir($currdir);
            if (! rmdir($location)) {
                return false;
            }
        } else if (file_exists($location)) {
            if (!unlink($location)) {
                return false;
            }
        }
        return true;
    }

// ミソは，mb_detect_encode()でどんな文字コードで圧縮されているかを自動的に検出している点．
// ただし，擬似RAWURLの場合はASCIIなので，副作用は無いはずなのでファイルシステムの文字コードへの変換を行う．
    function zipitem2currentCharset($str)
    {
        $encoding = mb_detect_encoding($str, 'auto');
//      $str = mb_convert_encoding($str, 'UTF-8', $encoding);
        if (!$encoding) return $str;
        $str = mb_convert_encoding($str, 'UTF-8', $encoding);
        // 擬似RAWURL＋強制S-JISの場合．パスとファイル名でコードが違うことに起因する問題
        if (is_fs_rawurl()) $str = fsCharset2currentCharset($str);
        return $str;
    }

// ファイルシステム文字コード混在時の対応
// displaydir() files/index.phpとlib/editor/htmlarea/coursefiles.php
// もし読み出したファイル名が古い文字コードをファイルシステムに
// 変換したものである（あるいは等価）ならば，旧ファイル名を利用する．
    function fs_readdir_for_displaydir($directory)
    {
//      if (!($file = readdir($directory))) return false;
        if (($file = readdir($directory)) === false) return false; // フォルダ名が'0'の場合に表示されなくなるバグ (2008/1/12) T.Shirai
        $oldfile = oldfsCharset2currentCharset($file);
        $oldfs   = currentCharset2oldfsCharset($oldfile);
        if ($oldfs == $file) {
            $file = $oldfile;
            if (is_fs_rawurl()) $file = fsCharset2currentCharset($file);
        } else {
            $file = fsCharset2currentCharset($file);
        }
        return $file;
    }

// moodledata/tempフォルダの下に作業用フォルダを作成する
// $foldername : 相対パス
function fs_make_temp_folder($foldername)
{
    global $CFG;
    // ログフォルダの確認（および作成）
    $fullpath = $CFG->dataroot.'/temp/'.$foldername;
    if (!is_dir($fullpath)) {
        if (!@fs_mkdir($fullpath, $CFG->directorypermissions)) return false;
        if (!is_dir($fullpath)) return false;
    }
    return $fullpath;
}

// moodledataフォルダの下に作業用フォルダを作成する
// $foldername : 相対パス
function fs_make_work_folder($foldername)
{
    global $CFG;
    // ログフォルダの確認（および作成）
    $fullpath = $CFG->dataroot.'/'.$foldername;
    if (!is_dir($fullpath)) {
        if (!@fs_mkdir($logpath, $CFG->directorypermissions)) return false;
        if (!is_dir($logpath)) return false;
    }
    return $fullpath;
}

// (Shirai077): シフトJISで記述されたテキストファイルを含むSCORMパッケージをUTF-8に変換して読み込む拡張 (2008/08/05)
// 指定されたフォルダ以下に存在するテキストファイルの文字コードを全てUTF-8に変換する
// (mod/scorm/lib.php)
    function convertText2utf8($dir, $html = true, $others = true)
    {
        if (!fs_file_exists($dir)) return;  // 念のため
        if (fs_is_file($dir)) {
            // ファイルの場合
            // mimetypeで判断
            $mimetype = mimeinfo('type', $dir);
            if (($mimetype != 'text/plain') && ($mimetype != 'text/html')) return;
            if (($mimetype == 'text/plain') && ($others == false)) return;
            if (($mimetype == 'text/html')  && ($html   == false)) return;
            // ファイルを読み出す
            $str = fs_file_get_contents($dir);
            // 最初からUTF-8ならば変換は行わない
            if (mb_detect_encoding($str, 'auto') === 'UTF-8') return;
            // UTF-8に変換して出力
            $str = mb_convert_encoding($str, 'UTF-8', 'auto');
            fs_file_put_contents($dir, $str);
            return;
        } else {
            // フォルダの場合
            $dirs = fs_opendir($dir);
            while (($ent = fs_readdir($dirs)) !== false) {
                if (($ent == '.') || ($ent == '..')) continue;
                // 再帰的に呼び出す
                convertText2utf8($dir.'/'.$ent, $html, $others);
            }
            closedir($dirs);
        }
        return;
    }

///////////////////////////////
// ユーザフィールド関係の関数群
///////////////////////////////

// ユーザープロフィールフィールドから特定のショートネームの値を取得する．
// もし項目が存在しない場合はfalseを返す．
// user/profile/lib.php中のfunction profile_display_fields($userid)を改造．
function get_userProfileField_value($userid, $shortname) {
    global $CFG, $USER;

    // もしログインユーザかつ設定済みならば即座に返答（値がfalseの場合は除く）
    if ($USER->id == $userid) {
        if (isset($USER->$shortname)) return $USER->$shortname;
    }
    // 湯川氏のコード
    require_once($CFG->dirroot.'/user/profile/lib.php');
    if (!($userid == -1)) {
        //ユーザープロファイルを取得
        $usr = fs_get_record('user', 'id', $userid);
        if (!$usr) {
             //エラー
        } else {
            //カスタムデータを読み取る
            profile_load_data($usr);
            //プロファイルを返す
            if (isset($usr->$shortname)) return $usr->$shortname;
        }
    }
    // それ以外の場合はデータベースを検索する（不要かも）
    if ($categories = fs_get_records_select('user_info_category', '', 'sortorder ASC')) {
        foreach ($categories as $category) {
            if ($fields = fs_get_records_select('user_info_field', "categoryid=$category->id", 'sortorder ASC')) {
                foreach ($fields as $field) {
/*
                    require_once($CFG->dirroot.'/user/profile/field/'.$field->datatype.'/field.class.php');
                    $newfield = 'profile_field_'.$field->datatype;
                    $formfield = new $newfield($field->id, $userid);
                    if ($formfield->is_visible() and !$formfield->is_empty()) {
                        print_row(s($formfield->field->name.':'), $formfield->display_data());
                    }
*/
// ここから追加
                    if ($field->shortname === $shortname) {
                        if ($datas = fs_get_records_select('user_info_data', "fieldid=$field->id")) {
                            foreach ($datas as $data) {
                                if ($data->userid === strval($userid)) {
                                    if (!empty($data->data)) return $data->data;
                                }
                            }
                        }
                    }
// ここまで追加
                }
            }
        }
    }
// ここから追加
    return false;
// ここまで追加
}

// ユーザープロフィールフィールドから特定のショートネームが存在するか確認．
// もし項目がデータベースに存在しない場合はfalseを返す．
// user/profile/lib.php中のfunction profile_display_fields($userid)を改造．
function is_exist_userProfileField($shortname) {
    global $CFG;

    if ($categories = fs_get_records_select('user_info_category', '', 'sortorder ASC')) {
        foreach ($categories as $category) {
            if ($fields = fs_get_records_select('user_info_field', "categoryid=$category->id", 'sortorder ASC')) {
                foreach ($fields as $field) {
                    if ($field->shortname === $shortname) return true;
                }
            }
        }
    }
    return false;
}

// 特定のユーザプロファイルフィールドを設定済みのユーザ群を返す関数
// リターン値は配列．$datasの一つを$dataとするならば，$data->dataが値，$data->useridがユーザID
function get_uids_basedon_userProfileField_value($shortname)
{
    if (empty($shortname)) return false;

    // ユーザプロファイルフィールドのカテゴリをリストアップ
    if ($categories = fs_get_records_select('user_info_category', '', 'sortorder ASC')) {
        foreach ($categories as $category) {
            // カテゴリに属するユーザプロファイルフィールドをリストアップ
            if ($fields = fs_get_records_select('user_info_field', "categoryid=$category->id", 'sortorder ASC')) {
                // リスト内を探索
                foreach ($fields as $field) {
                    if ($field->shortname === $shortname) {
                        // このフィールドIDを登録しているユーザを取得
                        if ($datas = fs_get_records_select('user_info_data', "fieldid=$field->id")) {
                            return $datas;
                        }
                    }
                }
            }
        }
    }
    return false;
}



// 氏名の並びをチェックする
// 戻り値： 'LF' : Lastname  Firstname (日本風):CJK
//          'FL' : Firstname Lastname  (欧米風)
//          'F'  : Firstname only
//          'L'  : Lastname only
function fullname_order($override = false)
{
    $user->lastname  = 'L';
    $user->firstname = 'F';
    $fullname = fullname($user, $override);
    if (empty($fullname)) return '';
    if ($fullname == 'L') return 'L';
    if ($fullname == 'F') return 'F';
    return str_replace(' ', '', $fullname);
}

// 評定用：姓，名，ＩＤナンバー／ユーザー名の文字列を設定に従って並べ直す
function fs_fullnameStrings($Firstname, $Lastname, $IDstring = null, $Usernamestring = null)
{
    $ret = '';
    if (fullname_order() == 'LF')   $ret .= $Lastname. $Firstname;
        else                        $ret .= $Firstname.$Lastname;
    if (fs_function_enable('FS_DISABLE_GRADE_ID2USERNAME')) 
                                    $ret .= $Usernamestring;
        else                        $ret .= $IDstring;
    return $ret;
}

// 主にcron.phpでPDF2JPEG，フォーラムダンプ，ブログエクスポートで発生したゴミ（moodledata/tmp内）を削除するために用意
// function fulldelete()をベースに開発
function cleanup_tmp_folder($location, $pasttime = 3600)
{
    $timenow  = time();
    if (fs_is_dir($location) and !fs_is_link($location)) {
        $currdir = fs_opendir($location);
        while (false !== ($file = fs_readdir($currdir))) {
            if ($file <> ".." && $file <> ".") {
                $fullfile = $location."/".$file;
                if (fs_is_dir($fullfile)) {
                    if (!fulldelete($fullfile)) {
                        closedir($currdir);
                        return false;
                    }
                } else {
                    if (fs_filemtime($fullfile) < ($timenow - $pasttime)) { // １時間経過後に削除
                        if (!fs_unlink($fullfile)) {
                            closedir($currdir);
                            return false;
                        }
                    }
                }
            }
        }
        closedir($currdir);
        if (fs_filemtime($location) < ($timenow - $pasttime)) { // １時間経過後に削除
            if (! fs_rmdir($location)) return false;
        }
    } else if (fs_file_exists($location)) {
        if (fs_filemtime($location) < ($timenow - $pasttime)) { // １時間経過後に削除
            if (!fs_unlink($location))  return false;
        }
    }
    return true;
}

// デバッグ用：$fsCFG変数のメンバを全て表示する
function print_fsCFG($return = false)
{
    global $fsCFG, $USER;

    if (!defined('FS_DEBUG_MODE') || !is_siteadmin($USER->id)) return;
    $no     = 1;
    $varray = get_object_vars($fsCFG);
    ob_start();
    foreach ($varray as $key => $value) {
        echo "[$no] $key = ";
        var_dump($fsCFG->$key);
        echo '<BR/>';
        $no++;
    }
    $msg = ob_get_contents();
    ob_end_clean();
    if ($return) return $msg;
        else     echo   $msg;
}

// フォーラム：チョイ読み機能はOnか？
// (Shirai080): フォーラム未読をクリアしないで投稿を閲覧する”チョイ読み”機能の追加 (2008/08/11)
function is_trialreading_on()
{
    if (!fs_function_enable('FS_DISABLE_FORUM_TRIALREADING')) return false;
    if (empty($_COOKIE['fs_trialreading_on'])) return false;
    return true;
}
// フォーラム：「チョイ読み中！」の表示
function print_trialreading_status()
{
    if (is_trialreading_on()) {
//      echo '<span style="color:red; font-weight:bold">'.get_string('trialreadingisworking', 'fs_moodle').'</span><br/>';
        echo '<span style="color:red; font-weight:bold">'.get_string('trialreadingisworking', 'fs_moodle').'</span>';
    }
}

// (Shirai157): ”このコンテンツを電子メール送信するボタン”機能の追加 (2009/07/04)
function is_send2me_on()
{
    if (!fs_function_enable('FS_DISABLE_SENDTHISCONTENTS2ME')) return false;
    if (empty($_COOKIE['fs_send2me_on'])) return false;
    return true;
}

// (Shirai161): ブログをエクスポートする機能の追加 (2009/07/25)
function can_export_blog($userid)
{
    global $USER, $fsCFG;

    if (!isloggedin()) return false;
    if (isguest() )    return false;
    if (!isset($USER->id) || !isset($userid)) return false;

    switch ($fsCFG->blogexport_capability) {
      case '0':
        return false;
      case '1': // 管理者のみ可能
        if (is_siteadmin($USER->id)) return true;
        return false;
      case '2': // 本人のみ可能
        if ($USER->id == $userid)    return true;
        return false;
      case '3': // 管理者と本人のみ可能
        if (is_siteadmin($USER->id)) return true;
        if ($USER->id == $userid)    return true;
        return false;
    }
    return false;
}

// (Shirai160): ブログにも投稿ごとに固有のIDを追加する改良 (2009/07/20)
// (Shirai163): ブログに返信機能を追加 (2009/08/26)
function link2blogEntry($postid, $linkonly = false)
{
    global $CFG;

    $url = public_wwwroot().'/blog/index.php?postid='.$postid;
    $prestr  = '<a href="'.$url.'">';
    $poststr = '</a>';
    if ($linkonly)  $output = $prestr.$url.$poststr;
      else          $output = '(ID:'.$prestr.$postid.$poststr.')';
    return $output;
}

// HTML出力関係
function color_red($str)
{
    return '<font color="#ff0000">'.$str.'</font>';
}

function color_blue($str)
{
    return '<font color="#0000ff">'.$str.'</font>';
}

////////////////////////////////////////////////////////////////////////////////
// 携帯電話などでは表示できない文字を自動的に置換する関数（文字コード版とHTML版）
// モバイル機器（特にUTF-8で三角記号が表示できない機種）を判定する
// 判定結果は$fsCFG->mobileに設定するので，fs_index.phpで一度実行すればあとは検査する必要なし．
// (2009/10/01)
function mobiledevice_check()
{
    global $fsCFG;
    if (empty($fsCFG->mobile)) {
        $fsCFG->mobile = false;
        if (!empty($_SERVER['HTTP_USER_AGENT'])) {
            $uagent = $_SERVER['HTTP_USER_AGENT'];
            foreach ($fsCFG->noArrowFont as $uas) {
                if (false !== strpos($uagent, $uas)) {
                    $fsCFG->mobile = true;
                    break;
                }
            }
        }
    }
}
function replace_character4mobile($char) // 未完成
{
    global $fsCFG;
    mobiledevice_check();
    if ($fsCFG->mobile) {
        return $char;
    } else return $char;
}
// 第２引数が指定されなかった場合は第１引数から推定して適当な文字列に変換する．
// 大抵の場合は第２引数を指定して使用すると思われる．
// (2009/10/01)
function replace_htmlchar4mobile($str, $rep = '')
{
    global $fsCFG;
    mobiledevice_check();
    if ($fsCFG->mobile) {
        if (empty($rep)) {
            switch (strtoupper($str)) {
                case '&#X25BA;':
                case '&#X25B6;':
                case '&RARR;':
                    return '&gt;';
                case '&#X25C4;':
                case '&#X25C0;':
                case '&LARR;':
                    return '&lt;';
                default:
                    return $str;
            }
        } else return $rep;
    } else return $str;
    return $str;
}

///////////////////////////////////////////////////////////////////////////
// ポップアップウィンドウに”ウィンドウを閉じる”ボタンを追加するための関数
// ほぼ同じ関数，function close_window_button()が，lib/weblib.phpにもあるが，
// 位置の制御を行いたい（インライン要素，センタリング）場合と，
// なによりもフレームを用いたウィンドウを閉じることができないので，
// 白井が追加する箇所にはこの関数を用いる．
function output_CloseWindowButton($center = true, $frame = false)
{
//  $str  = '<Form>';
    $str  = '';
    if ($center) $str .= '<center>';
    $str .= '<Input type="button" value="'.get_string('closewindow').'" onClick="javascript:';
    if ($frame) $str .= 'parent'; else $str .= 'window';
    $str .= '.close();">';
    if ($center) $str .= '</center>';
//  $str .= '</Form>';
    echo $str. "\n";
}

// 白井のfs_moodleに関する情報のサイトへのリンクを出力／表示
function link2fs_wiki_direct($id_str, $title = '', $display=false)
{
    global $fsCFG;
    $str  = '<a href="'.$fsCFG->officialWikiURI.'&amp;page='.$id_str.'" target="_blank"';
    if (!empty($title)) $str .= ' title="'.$title.'"';
    $str .= '>'.$id_str.'</a>';
    if ($display) echo $str;
    return $str;
}

function link2fs_wiki($id_str, $title = '', $display=false)
{
    global $fsCFG;
    $str  = '(<a href="'.$fsCFG->officialWikiURI.'&amp;page='.$id_str.'" target="_blank"';
    if (!empty($title)) $str .= ' title="'.$title.'"';
    $str .= '>'.$id_str.'</a>)';
    if (!empty($fsCFG->localWikiURI)) {
        $str .= '&nbsp;/&nbsp;(<a href="'.$fsCFG->localWikiURI.'/'.$id_str.'.html" target="_blank">ローカル</a>)';
    }
    if ($display) echo $str;
    return $str;
}
function link2shirai($num, $display=false)
{
    $num = str_pad($num, 3, '0', STR_PAD_LEFT);
    return link2fs_wiki('Shirai'.$num, '', $display);
}
function link2ie($num, $display=false)
{
    $num = str_pad($num, 3, '0', STR_PAD_LEFT);
    return link2fs_wiki('IE_Problem'.$num, '', $display);
}
function link2debug($num, $display=false)
{
    $num = str_pad($num, 3, '0', STR_PAD_LEFT);
    return link2fs_wiki('Debug'.$num, '', $display);
}
function link2third($num, $display=false)
{
    $num = str_pad($num, 3, '0', STR_PAD_LEFT);
    return link2fs_wiki('3rdParty'.$num, '', $display);
}

/////////////////////////////////////
// 汎用のログファイル名を管理する関数
/////////////////////////////////////
// ログファイル名を取得（電子メール関係と電子メールでブログを投稿する機能で利用）
function get_detaillog_filename($formatname)
{
    global $fsCFG;
    switch ($formatname) {
        case 'email_detaillog_filenameformat' :
        case 'email_detaillog_errorfilenameformat' :
        case 'm2b_log_filenameformat' :
            return eval('return '.$fsCFG->$formatname.';');
        default:
            return 'default.log';
    }
}
// ログファイルをmoodledata/logフォルダに作成するための準備
// フォルダの確認（もし無いならば作成），日付を基にしてファイルを追記でオープン
// フォルダ作成に失敗したらfalseを返す．
function fopen_for_email_detaillog($formatname)
{
    global $CFG, $fsCFG;
    // フォルダの作成（確認）
    $output_dir = $CFG->dataroot.'/log';
    if (!is_dir($output_dir)) {
        if (!@mkdir($output_dir, $CFG->directorypermissions)) return false;
    }
    // ログファイルの作成（追記モード）
    $logfilename = get_detaillog_filename($formatname);
    return @fopen($output_dir.'/'.$logfilename, 'a');
}
///////////////////////////////////////////////////////////////////////////
// 電子メール関係の関数
///////////////////////////////////////////////////////////////////////////
// (Shirai105): 電子メール送信時の詳細なログを残す機能を追加（デフォルトで無効） (2008/12/11)]
// 実際には以下の関数を使ってログの各行を出力する
// こちらはメール送信元と送信先が判明している上位レベルの関数用
function record_email_detaillog($module, $from, $to, $action, $status = '', $message = '')
{
    global $CFG, $fsCFG;
    // チェック
    if (!fs_function_enable('FS_ENABLE_EMAIL_DETAILLOG')) return;  // このチェックは呼び出し側では省略しましょう．
    $from = stripslashes($from);
    $to   = stripslashes($to);
    if ($from == '') $from = '('.$CFG->noreplyaddress.')';
    if ($message) $message = str_replace("\r", '', str_replace("\n", ';', $message));
    if (eregi('ERROR', $status)) $error = true; else $error = false;
    // 本体
    $logs = date('Y/m/d H:i:s')." ($module) ";
    if ($status != '') $logs .= "[$status] ";
    if ($fsCFG->email_detaillog_includingaddress > 0) {
        if ($to   == '') $to = '(Error:Nothing)';
        $logs.= 'FROM= '. $from.' ';
        $logs.= 'TO= '.   $to.' ';
    } else if ($fsCFG->email_detaillog_includingaddress == 0) { // 頭一文字だけ残す
        $logs.= 'FROM= '. substr($from, 0, 1).preg_replace('/[^\.@-]/','*',substr($from, 1)).' ';
        $logs.= 'TO= '.   substr($to  , 0, 1).preg_replace('/[^\.@-]/','*',substr($to  , 1)).' ';
    } // 負の値の場合は一切記録しない
    $logs.= "[$action]";
    if (($message != '') && ($fsCFG->email_detaillog_includingaddress > 0)) $logs .= " \"$message\"";
    $logs.= "\n";
    // ログの出力
    if ($fres = fopen_for_email_detaillog('email_detaillog_filenameformat')) {
        fwrite($fres, $logs);
        fclose($fres);
    }
    if ($error && $fres = fopen_for_email_detaillog('email_detaillog_errorfilenameformat')) {
        fwrite($fres, $logs);
        fclose($fres);
    }
}
// こちらはclass.smtp.phpのような下位レベルの関数用
function record_email_detaillog_lowlevel($module, $action, $status, $message = '')
{
    global $CFG, $fsCFG;
    // チェック
    if (!fs_function_enable('FS_ENABLE_EMAIL_DETAILLOG')) return;   // このチェックは呼び出し側では省略しましょう．
    if (!$fsCFG->email_report_lowlevel_log) return;                 // このチェックは呼び出し側では省略しましょう．
    if ($message) $message = str_replace("\r", '', str_replace("\n", ';', $message));
    if (eregi('ERROR', $status)) $error = true; else $error = false;
    // 本体
    $logs = '-->'.date('Y/m/d H:i:s')." ($module) ";
    $logs.= "[$action][$status]";
    if (($message != '') && ($fsCFG->email_detaillog_includingaddress > 0)) $logs .= " \"$message\"";
    $logs.= "\n";
    // ログの出力
    if ($fres = fopen_for_email_detaillog('email_detaillog_filenameformat')) {
        fwrite($fres, $logs);
        fclose($fres);
    }
    if ($error && $fres = fopen_for_email_detaillog('email_detaillog_errorfilenameformat')) {
        fwrite($fres, $logs);
        fclose($fres);
    }
}
// smtp専用
function record_smtp_detalilog($action, $status, $message = '')
{
    record_email_detaillog_lowlevel('SMTP', $action, $status, $message);
}

// (Shirai115): 管理者宛にメッセージを送る機能（関数）を追加 (2009/01/21)
// もし，電子メールも同時に送信するのならば$messagetypeを'direct'とする．
// 'directNoEmail'以外の場合，条件を満たす場合はメッセージに加えて電子メールも送信される．
// $subject: タイトル
// $message: 本文
// $messagetype: 'direct' or 'directNoEmail'
function message_post_to_admin($subject, $message, $messagetype = 'directNoEmail')
{
    global $USER;
    global $CFG;

    require_once($CFG->dirroot.'/message/lib.php');
    if (!isset($USER)) $userfrom = get_admin(); else $userfrom = $USER;
    $message = $subject."\n".$message;
    message_post_message($userfrom, get_admin(), addslashes($message), FORMAT_PLAIN, $messagetype);
}

// moodledata/configフォルダの有無のチェックと作成
function fs_check_config_folder($printout = false)
{
    global $CFG;

    // フォルダを確認
    if (!file_exists(FSCONFIGDIR)) {
        fs_mkdir(FSCONFIGDIR);
        if (!fs_is_dir(FSCONFIGDIR)) {
            // moodledata/configフォルダの作成に失敗しました．
            if ($printout) print_string('error_cannotmakefolder', 'fs_moodle', FSCONFIGDIR);
              else         print_error('error_cannotmakefolder' , 'fs_moodle', FSCONFIGDIR);
            die;
        }
    } else {
        if (!fs_is_dir(FSCONFIGDIR)) {
            // moodledata/configはフォルダではなくファイルです．
            if ($printout) print_string('error_forlderisfile', 'fs_moodle', FSCONFIGDIR);
              else         print_error('error_forlderisfile' , 'fs_moodle', FSCONFIGDIR);
            die;
        }
    }
}

// ファイル名の拡張子のみを変更する関数
// （注意）もし拡張子が存在しない場合は追加する
function change_extension($filename, $extension)
{
    $extpos = mb_strrpos(fs_basename($filename), '.');
    if ($extpos) {
        $newfilename = fs_dirname($filename);
        if (!empty($newfilename)) $newfilename .= '/';
        $newfilename .= mb_substr(fs_basename($filename), 0, $extpos).'.'.$extension;
    } else $newfilename = $filename.'.'.$extension;
    return $newfilename;
}

// (Shirai182): 二つのURLから一つのMoodleにアクセスしているシステムにおいて外部に供給するURLのベースアドレス（通常は$CFG->wwwroot）を統一できる改良 (2010/03/21)
// 以下の機能において$CFG->wwwrootをそのまま使用すると支障が出る．
// (Shirai157): ”このコンテンツを電子メール送信するボタン”機能の追加 (2009/07/04)
// (Shirai002): フォーラムへの書き込みに一つずつ固有のナンバを表示する（吉田さん）
// (Shirai160): ブログにも投稿ごとに固有のIDを追加する改良 (2009/07/20)
// (Shirai163): ブログに返信機能を追加 (2009/08/26)
function public_wwwroot()
{
    global $fsCFG, $CFG;
    if (fs_function_enable('FS_ENABLE_USEPUBLICWWWROOT')) return $fsCFG->publicwwwroot;
    return $CFG->wwwroot;
}

// (Shirai183): カレンダーの土日と祝日に文字色を付ける改良 (2010/04/01)
// 色指定（$colorstr）は#付きの文字列（例： '#FF0000'）
function fs_add_eventcolor($prefixstr, $colorstr = '', $description = ' ', $weekend = true)
{
    global $fsCFG;
    // チェック
    if (strlen($prefixstr) == 0) return false;
    // 値の設定（色指定がブランク）
    if ($colorstr == '') {
        // 削除
        if ($fsCFG->eventcolor[$prefixstr]) unset($fsCFG->eventcolor[$prefixstr]);
        return true;
    }
    // 追加
    $fsCFG->eventcolor[$prefixstr] = (object)NULL;
    $fsCFG->eventcolor[$prefixstr]->color       = $colorstr;
    $fsCFG->eventcolor[$prefixstr]->description = $description;
    $fsCFG->eventcolor[$prefixstr]->weekend     = $weekend;
    return true;
}

// 与えられたイベント名の頭に$fsCFG->eventcolorに含まれる接頭辞があったら取り除いた結果を返す
function fs_real_eventname($name)
{
    global $fsCFG;
    if (!fs_function_enable('FS_DISABLE_CALENDARCOLOREDSPECIAL')) return $name;
    foreach($fsCFG->eventcolor as $prefixstr => $colorobj) {
        if (strncmp($name, $prefixstr, strlen($prefixstr)) == 0) return substr($name, strlen($prefixstr));
    }
    return $name;
}

// 与えられた日のイベントに識別子を含むイベントがあるかどうかをチェックして色の候補を返す
function fs_check_events_for_detecting_color_of_day($day, $eventsbyday, $events, $daycolor, $daycolors)
{
    if (isset($eventsbyday[$day])) {
        foreach($eventsbyday[$day] as $key => $eventid) {
            if (!isset($events[$eventid])) continue;
            $event = $events[$eventid];
            $daycolors = fs_check_this_event_for_detecting_color_of_day($event, $daycolor, $daycolors);
        }
    }
    return $daycolors;
}

// 与えられたイベントに識別子を含むイベントがあるかどうかをチェックして色の候補を返す
function fs_check_this_event_for_detecting_color_of_day($event, $daycolor, $daycolors)
{
    global $fsCFG;
    if (fs_function_enable('FS_DISABLE_CALENDARCOLOREDSPECIAL') and (strlen($event->name) != 0)) {
        $prioritynum = 0;
        foreach($fsCFG->eventcolor as $prefixstr => $colorobj) {
            $prioritynum++;
            if (strncmp($event->name, $prefixstr, strlen($prefixstr)) == 0) {
//                      if ($daycolor != FSCALENDARCOLOR_SUN) $daycolors[$prioritynum] = $eventcolor;
                if (empty($daycolor) || !$colorobj->weekend) $daycolors[$prioritynum] = $colorobj->color;
                break;
            }
        }
    }
    return $daycolors;
}

// 与えられた$daycolor, $daycolorsに従ってスタイル文字列を生成
function fs_geenerate_color_style_of_calendar($daycolor, $daycolors = array())
{
    $colorstr = '';
    if (fs_function_enable('FS_DISABLE_CALENDARCOLOREDWEEKEND')) {
        if (!empty($daycolor)) $colorstr = ' style="color:'.$daycolor.';" ';
    }
    if (fs_function_enable('FS_DISABLE_CALENDARCOLOREDSPECIAL') and (count($daycolors) != 0)) {
        ksort($daycolors);
        $daycolor = array_shift($daycolors);
        if ($daycolor) $colorstr = ' style="color:'.$daycolor.';" ';
    }
    return $colorstr;
}

// 宣言済みのイベントカラーを表形式で表示する
function fs_display_declared_eventcolor($force = false)
{
    global $fsCFG;
    if (($force) or (fs_function_enable('FS_DISABLE_CALENDARCOLOREDSPECIAL'))) {
        if (empty($fsCFG->eventcolor)) {
//          echo color_red(get_string('therearenoeventcolors', 'fs_moodle')).'<br />';
        } else {
            echo '<table align=center cellpadding=5pix frame=border style="border: 1px solid #000000">';
            echo '<caption>';
            echo get_string('settingofeventcolor', 'fs_moodle');
            echo fs_helpbutton('settingofeventcolor', get_string('settingofeventcolor', 'fs_moodle'), 'fs_moodle', true, false, '', true);
            echo '</caption>';
            echo '<tr bgcolor=#F0F0F0>';
            echo '<th>'.get_string('eventcolorpriority',    'fs_moodle').'</th>';
            echo '<th>'.get_string('eventcolorprefix',      'fs_moodle').'</th>';
            echo '<th>'.get_string('eventcolorcode',        'fs_moodle').'</th>';
            echo '<th>'.get_string('eventcolordescription', 'fs_moodle').'</th>';
            echo '<th>'.get_string('eventcolorweekend',     'fs_moodle').'</th>';
            echo '</tr>';
            $i = 1;
            foreach ($fsCFG->eventcolor as $prefix => $eventcolor) {
                echo '<tr align=center>';
                echo '<td>'.$i.'</td>';
                echo '<td>'.$prefix.'</td>';
                echo '<td>'.$eventcolor->color.'<font color='.$eventcolor->color.'>■</font></td>';
                echo '<td>'.$eventcolor->description.'</td>';
                echo '<td>'.($eventcolor->weekend ? 'true' : 'false').'</td>';
                echo '</tr>';
                $i++;
            }
            echo '</table>';
        }
    }
}

// (Shirai189): フォーラムの貼付画像のサイズを制限する機能の追加 (2010/05/20)
// 画像ファイルを読み出し，指定された制限値よりも大きい場合はサイズ指定をして縮小表示する．
// 最大値に0を指定した方向には大きさの制限をしない．
function fs_image_width_height($fullpath)
{
    global $fsCFG;
    $sizestr = '';
    if (fs_function_enable('FS_ENABLE_RESTRICT_IMAGESIZE')) {
        $max_x = $fsCFG->blogimagemax_x;
        $max_y = $fsCFG->blogimagemax_y;
        // 初期化
        $ratio_x = $ratio_y = 1;
        // 画像のサイズを取得
        $imsize = fs_getimagesize($fullpath);
        // 個別の比率の計算
        if ($max_x != 0) $ratio_x = $max_x / $imsize[0];
        if ($max_y != 0) $ratio_y = $max_y / $imsize[1];
        if ($imsize[0] <= $max_x) $ratio_x = 1;
        if ($imsize[1] <= $max_y) $ratio_y = 1;
        // 1%は誤差
        if (abs($ratio_x - 1.0) <= 0.01) $ratio_x = 1;
        if (abs($ratio_y - 1.0) <= 0.01) $ratio_y = 1;
        // 比率の確定
        if ($ratio_x < $ratio_y)          $ratio = $ratio_x;
            else if ($ratio_x > $ratio_y) $ratio = $ratio_y;
            else                          $ratio = $ratio_x;
        // 文字列の作成
        if ($ratio == 1) $sizestr = ' width="'.$imsize[0].                '" height="'.$imsize[1].'" ';
            else         $sizestr = ' width="'.(int)($imsize[0] * $ratio).'" height="'.(int)($imsize[1] * $ratio).'" ';
    }
    return $sizestr;
}

// (Shirai190): ユーザ画像の表示範囲を制限可能とする機能の追加 (2010/06/01)
// (Shirai190): ここから
// lib/deprecatedlib.php中の function isstudent($courseid=0, $userid=0)をベースに．
function fs_is_legacy_role($rolename, $courseid=0, $userid=0) {
    global $CFG;

    if (empty($CFG->rolesactive)) {
        return false;
    }

    if ($courseid == 0) {
        $context = get_context_instance(CONTEXT_SYSTEM);
    } else {
        $context = get_context_instance(CONTEXT_COURSE, $courseid);
    }

    return has_capability('moodle/legacy:'.$rolename, $context, $userid, false);
}

// レガシーロールが管理者，コース作成者，コース編集者，教師ならば教師とする
function fs_is_teacher($userid = 0)
{
    return (fs_is_legacy_role('admin', 0, $userid)          or fs_is_legacy_role('coursecreator', 0, $userid)
         or fs_is_legacy_role('editingteacher', 0, $userid) or fs_is_legacy_role('teacher',        0, $userid));
}

// レガシーロールが管理者，コース作成者，コース編集者，教師ではないならば学生とする
// つまりゲストや認証済みユーザも含まれる
function fs_is_student($userid = 0)
{
    return !fs_is_teacher($userid);
}

function fs_can_display_userpicture($user)
{
    global $fsCFG, $USER;

    // エラーチェック
    if (!fs_function_enable('FS_ENABLE_PRINTUSERPICTURELEVEL')) return true;
    if (empty($fsCFG->userpict_level)) return true;
    if ($fsCFG->userpict_level == 99) return false;
    if (empty($USER->id)) return false;
    if (empty($user->id)) return false;
    // 自分自身の顔写真は表示しても良い
    if ($USER->id == $user->id) return true;
    // 制限する画像のターゲット（学生のみか，全ユーザか）を判別
    $level = $fsCFG->userpict_level;
    if ($level > 10) {
        $targetall = true;
        $level -= 10;
    } else $targetall = false;
    // レベルに応じた処理
    $candisplay = true;
    switch ($level) {
        case 1: // 制限なし
            return true;
        case 2: // ログインしていればＯＫ（ゲストも）
            break;
        case 3: // ログインしていればＯＫ（ゲストは不可）
            if (fs_is_legacy_role('guest'))   $candisplay = false;
            break;
        case 4: // 教師のみＯＫ
            if (fs_is_student()) $candisplay = false;
            break;
        case 5: // 管理者のみＯＫ
            if (empty($USER->id))             $candisplay = false;
            if (!is_siteadmin($USER->id))     $candisplay = false;
            break;
        default:
            return true;
    }
    if (!isloggedin()) $candisplay = false;

    // 対象の画像は？
    // 全てが制限対象
    if ($targetall) return $candisplay;
    // 教師は制限対象外
    if (fs_is_teacher($user->id)) return true;

    return $candisplay;
}

// 指定されたユーザのレガシーロールの設定を表示する
function print_legacy_role_table($userid = 0, $courseid = 0)
{
    echo '<table align=center cellpadding=5pix frame=border style="border: 1px solid #000000">';
    echo '<caption>';
    echo get_string('tableoflegacyroleassignment', 'fs_moodle');
    echo '</caption>';
    echo '<tr bgcolor=#F0F0F0>';
    echo '<th align="center">'.get_string('administrator').      '<br />admin</th>';
    echo '<th align="center">'.get_string('coursecreators').     '<br />course creator</th>';
    echo '<th align="center">'.get_string('editingteachershort').'<br />editing teacher</th>';
    echo '<th align="center">'.get_string('teachers').           '<br />teacher</th>';
    echo '<th align="center">'.get_string('students').           '<br />student</th>';
    echo '<th align="center">'.get_string('guest').              '<br />guest</th>';
    echo '<th align="center">'.get_string('authenticateduser').  '<br />authenticated user</th>';
    echo '</tr>';
    echo '<tr align=center>';
    echo '<td>'.(fs_is_legacy_role('admin',          0, $userid) ? '○' : '×').'</td>';
    echo '<td>'.(fs_is_legacy_role('coursecreator',  0, $userid) ? '○' : '×').'</td>';
    echo '<td>'.(fs_is_legacy_role('editingteacher', 0, $userid) ? '○' : '×').'</td>';
    echo '<td>'.(fs_is_legacy_role('teacher',        0, $userid) ? '○' : '×').'</td>';
    echo '<td>'.(fs_is_legacy_role('student',        0, $userid) ? '○' : '×').'</td>';
    echo '<td>'.(fs_is_legacy_role('guest',          0, $userid) ? '○' : '×').'</td>';
    echo '<td>'.(fs_is_legacy_role('user',           0, $userid) ? '○' : '×').'</td>';
    echo '</tr>';
    echo '</table>';    
}
// (Shirai190): ここまで

// MoodleネットワークでProxyを使用しない（例外）アドレスを指定する（c.f. Shirai215）
// 設定用関数（fsconfig_option()でのみ使用）
function fs_add_mnet_exception_usingproxy($addr = NULL)
{
    global $fsCFG;

    if (empty($addr)) {
        $fsCFG->mnet_proxy_disable = true;
    } else {
        if (substr($addr, -1, 1) == '/') $addr = substr($addr, 0, -1);  // 末尾のスラッシュだけは取り除こう
        $fsCFG->mnet_proxy_addr[] = $addr;
    }
}
// これからアクセスしようとするサイトはProxyを使わないサイトか？
// mnet/lib.phpがインクルードされた状態でのみ使用可能
// Proxyを使うサイトの時のみTrue
function fs_mnet_check_usingproxy($wwwroot = NULL)
{
    global $CFG, $fsCFG;
    // Proxyを絶対に使わない
    if (empty($CFG->proxyhost))             return false;   // そもそもProxyを使う設定ではない
    if (!empty($fsCFG->mnet_proxy_disable)) return false;   // 全アドレスに対してProxyの使用を禁止している場合
    if (empty($wwwroot))                    return false;   // なんだか分からないがおかしい場合
    // Proxyを必ず使う
    if (!isset($fsCFG->mnet_proxy_addr) or (count($fsCFG->mnet_proxy_addr) <= 0)) return true;

    // それ以外の場合（mnet/peer.phpを参考に）

    // 末尾に/があったら取り除く
    if (substr($wwwroot, -1, 1) == '/') $wwwroot = substr($wwwroot, 0, -1);
    $hostname = mnet_get_hostname_from_uri($wwwroot);

    // Get the IP address for that host - if this fails, it will
    // return the hostname string
    $ip_address = gethostbyname($hostname);

    // ではチェックしよう
    foreach ($fsCFG->mnet_proxy_addr as $except_addr) {
        $hostname = mnet_get_hostname_from_uri($except_addr);
        if (gethostbyname($hostname) == $ip_address) {
            return false;
        }
    }
    return true;
}

// Moodleのバージョンを確認するための新しい関数
// メジャーナンバー 1.8, 1.9, 2.0, 2.1, 2.2, 2.3 など．
// 戻り値は一応，文字列だが数値としても扱うことが可能
function fs_get_major_version()
{
    global $CFG;
    $ver_array = explode('.', $CFG->release);
    $ver_string = $ver_array[0].'.'.$ver_array[1];
    return $ver_string;
}

// Moodleのバージョン($version）を取得する
function fs_get_moodle_version() {
    global $version;
    global $CFG;

    if (isset($version)) return $version;
    return $CFG->version;
}
// Moodleのリリース($release)を取得する
function fs_get_moodle_release() {
    global $release;
    global $CFG;

    if (isset($release)) return $release;
    return $CFG->release;
}

// Moodle2以降専用
function fs_doc_link_internal($path, $text = '', $forcepopup = false)
{
    global $OUTPUT;

    // lib/outputrenderer.php中のdoc_link()をオーバーライドする
    // もしオリジナルで引数の数が変更された場合に一箇所で対応できるように
    // 三番目の引数はtrueで自サイトを参照，という予定だったが，Moodle2.3以降のみ引数がひとつ追加されたので
    // $pathの頭に"fs_moodle:"を追加することで区別するようにfs_moodle5.00.02以降は変更
    return $OUTPUT->doc_link('fs_moodle:'.$path, $text, $forcepopup);
}

// (Shirai003): Backup/Restoreの際のログを記録してデバッグを助ける機能の追加 (2013/10/12)
// Moodle2.4以降でコースバックアップ／リストア／インポートの処理をmoodledata/temp/backup/backupRestoreDetail.logに書き出す
function _fs_log_output($str) {
    global $CFG;
    $dest = $CFG->dataroot.'/temp/backup/backupRestoreDetail.log';
    if ($fp = fopen($dest, 'a')) {
        fwrite($fp, date('c').':'.$str."\n");
    }
    fclose($fp);
}
// 以下を用いる：現状はすべて等価 : $str1はパス，あるいはメッセージ
function fs_log_backup($str1, $str2 = '') {
    global $fsCFG;
    if (!fs_function_enable('FS_ENABLE_DETAILLOG_BACKUPRESTORE')) return;
    if ($str2 !== '') _fs_log_output($str1.' : '.$str2);
        else          _fs_log_output($str1);
}
function fs_log_restore($str1, $str2 = '') {
    global $fsCFG;
    if (!fs_function_enable('FS_ENABLE_DETAILLOG_BACKUPRESTORE')) return;
    if ($str2 !== '') _fs_log_output($str1.' : '.$str2);
        else          _fs_log_output($str1);
}
function fs_log_import($str1, $str2 = '') {
    global $fsCFG;
    if (!fs_function_enable('FS_ENABLE_DETAILLOG_BACKUPRESTORE')) return;
    if ($str2 !== '') _fs_log_output($str1.' : '.$str2);
        else          _fs_log_output($str1);
}

// 汎用的なデバッグ用の関数：変数の型と内容を文字列に出力
function fs_var2str($var) {
    ob_start();
    var_dump($var);
    return ob_get_clean();
}

// パス，関数名，クラス名を文字列に整形する
// ex1) fs_class2str(__FILE__, __LINE__)
// ex2) fs_class2str(__FILE__, __LINE__, __FUNCTION__)
// ex3) fs_class2str(__FILE__, __LINE__, __FUNCTION__, $this)
function fs_class2str($path, $line, $function = null, $obj = null) {
    // パスの追加
    $str = $path."($line)";
    // 関数名の追加
    if ($function !== null) $str .= ' : '. $function.'()';
    // クラス名の取得と追加（ある場合）
    if ($obj != null) {
        if (($class_name = get_class($obj)) !== false) $str .= ' : class = '.$class_name;
    }
    return $str;
}

// デバッグ用：文字列を切り分けて表示（ANKのみ）
// リバースプロキシー環境ではURLが改竄されてしまうので．
function fs_strsplitdisplay($src, $isdisplay = true) {
    $str = '';
    for ($i = 0; $i < strlen($src); $i++) {
        $str .= substr($src, $i, 1). ' ';
    }
    if ($isdisplay) echo $str;
    return $str;
}

?>
