$timestamp_newest ) { $timestamp_newest = filemtime( $_SERVER['DOCUMENT_ROOT'] . $comp ); } } // 配列に代入 $data_xml = array( 'data' => $temp_data_xml, 'path' => $name_xml, 'id' => $info["id"], 'entity' => $info["entity"], 'date' => $timestamp_newest ); $data_html = xml_to_html( $mode, $data_xml ); // html_path取得。最初のデータ持ち込み $vdir = get_vd( $data_xml["id"], $data_html ); $temp_hp = ""; foreach( $vdir as $value ) { if ( $value['path'] ) { if( $value['subject'] == 'Arielworks.net' ) { $temp_hp .= '
  • ' . $value['subject'] . "
  • \n"; } else { $temp_hp .= '
  • ' . $value['subject'] . "
  • \n"; } } else { if( $value['subject'] == 'Arielworks.net' ) { $temp_hp .= "
  • " . $value['subject'] . "
  • \n"; } else { $temp_hp .= "
  • " . $value['subject'] . "
  • \n"; } } } $html_path = $temp_hp; // 最後に少し整形して出力。 $data_html = '' . "\n" . $data_html; $data_html = preg_replace( "/ xmlns=\"\"/", "", $data_html ); // 現在地を挿入。DOMが使えないので単純な置換で我慢 $data_html = str_replace( "", "\n
    \n
      \n" . $html_path . "
    \n
    \n
    ", $data_html ); $data_html = preg_replace( "|\s*?|s", "
      \n" . $html_path . "
    \n ", $data_html ); $data_html = preg_replace( "/
    \s*/is", '
    ', $data_html );
    	$data_html = preg_replace( "/\s*<\/pre>/is", '
    ', $data_html ); $data_html = preg_replace( "//is", '', $data_html ); $data_html = preg_replace( "//is", '', $data_html ); $data_html = preg_replace( "/(<.*?[^ ])\/>/is", "$1 />", $data_html ); // Last-Modified用にHimmelも合わせた最終更新時間を算出 $timestamp_sora = filemtime( $_SERVER["DOCUMENT_ROOT"] . "/himmel/sora.php" ); $timestamp_lemmih = filemtime( $_SERVER["DOCUMENT_ROOT"] . "/himmel/lemmih.inc" ); $timestamp_rsd = filemtime( $_SERVER["DOCUMENT_ROOT"] . "/himmel/rsd.xsl" ); $timestamp_newest_all = max( $timestamp_newest, $timestamp_sora, $timestamp_lemmih, $timestamp_rsd ); // etag生成 $etag = md5( $data_xml["id"] . $timestamp_newest_all ); // If-Modified-Sinceに対応 if( $request_headers["If-Modified-Since"] ) { $since = parse_http_date( $request_headers["If-Modified-Since"] ); if( $since["timestamp"] >= $timestamp_newest_all ) { header( "HTTP/1.1 304 Not Modified" ); header( "Etag: \"$etag\"" ); exit(); } } // -------------------------------------------------------------------- // コンテントネゴシエーション // application/xhtml+xmlに対応しているUAに対してはヘッダーを出力する // -------------------------------------------------------------------- $ha = explode( ',', $request_headers["Accept"] ); if ( in_array( 'application/xhtml+xml', $ha ) ) { header( 'Content-type: application/xhtml+xml' ); } else { header( "Content-Type: text/html; charset=UTF-8" ); } // -------------------------------------------------------------------- // HTTPヘッダ出力 header( "Last-Modified: " . gmdate( "D, d M Y H:i:s", $timestamp_newest_all ) . " GMT" ); header( "Content-Style-Type: text/css" ); header( "Content-Script-Type: text/javascript" ); header( "Etag: \"$etag\"" ); // -------------------------------------------------------------------- // IEの互換モード回避 // -------------------------------------------------------------------- if ( ! preg_match( "/IE 6/", $_SERVER['HTTP_USER_AGENT'] ) ) { print '' . "\n"; } // -------------------------------------------------------------------- // 本体出力 print $data_html; // -------------------------------------------------------------------- } // ---------------------------------------------------------------------------- // XSLT処理用 // ---------------------------------------------------------------------------- function xml_to_html( $mode, $data_xml ) { // 情報受け渡し用配列 $info_xml = array(); // 更新時間。WWWC、ページ情報用 $info_xml['update_wwwc'] = date( "Y/m/d H:i:s", $data_xml["date"] ); $info_xml['update_ymd'] = date( "Y-m-d", $data_xml["date"] ); // ID $info_xml['id'] = $data_xml["id"]; // XSLT関数のURI基底をハック $data_xml['data'] = preg_replace( "//", "", $data_xml['data'] ); // 配列に代入 $data_xslt = array( '/_xml' => $data_xml['data'] ); // XSLT処理 $handle_xslt = xslt_create(); $data_proceeded = xslt_process( $handle_xslt, "arg:/_xml", "file://" . $_SERVER['DOCUMENT_ROOT'] . "/himmel/rsd.xsl", null, $data_xslt, $info_xml ); xslt_free($handle_xslt); return $data_proceeded; } // ---------------------------------------------------------------------------- function get_vd( $target, $data_first = "", $loop = 0 ) { // 無限ループはまずいので適当にカット if ($loop > 20) { exit_with_xml( '無限ループになっています。' ); } // ディレクトリ名だった場合は/index.xmlを付ける if( substr( $target, -1, 1 ) == '/' ) { $target .= 'index.xml'; } elseif ( is_dir( $_SERVER['DOCUMENT_ROOT'] . $target ) ) { $target .= '/index.xml'; } $vdir_target = ''; $title_target = ''; if( $loop == 0 ) { // 1回目はwith_xmlを考慮して持ち込まれたデータを元に情報を取得 $data_target = $data_first; // もしあれば上位ディレクトリを取得。正規表現で我慢 if ( preg_match( "//", $data_target, $regs ) ) { $vdir_target = $regs[1]; } // タイトルを取得。 if ( preg_match( "/(.*?)<\/title>/is", $data_target, $regs ) ) { $title_target = $regs[1]; } } else { // 2回目以降はXMLファイルがあるかチェック。 // 有った場合はとタイトルをゲットする if ( file_exists( $_SERVER['DOCUMENT_ROOT'] . $target ) ) { if ( $handle_target = fopen( $_SERVER['DOCUMENT_ROOT'] . $target, "r" ) ) { flock( $handle_target, LOCK_SH ); $data_target = fread( $handle_target, filesize( $_SERVER['DOCUMENT_ROOT'] . $target ) ); flock( $handle_target, LOCK_UN ); fclose( $handle_target ); } // もしあれば上位ディレクトリを取得。 if ( preg_match( "//", $data_target, $regs ) ) { $vdir_target = $regs[1]; } // タイトルを取得。 if ( preg_match( "/(.*?)<\/title>/is", $data_target, $regs ) ) { $title_target = $regs[1]; } // ファイルがなかったら現在のパスからゲットする。 } else { // 分割して最後の一個はタイトルに、再結合して上位ディレクトリに $target_exp = explode( '/', $target ); array_pop( $target_exp ); $title_target = array_pop( $target_exp ); $vdir_target = implode( '/', $target_exp ); } } // hoge - は削除 if( preg_match( "/^.*? - (.*)$/", $title_target, $tit ) ) { $title_target = $tit[1]; } // 親取得ルーチン // vdir_target が空だったら、一個上かそのディレクトリのindex.xml if( $vdir_target == "" ) { // index.xml以外だったらそのディレクトリを取得する if( basename( $target, '.xml' ) != 'index' ) { $dir_oya = dirname( $target ); } else { // 現在のディレクトリを分割 $temp_oya = explode( "/", $target ); // 親ディレクトリは一個上 // よってファイル名とディレクトリ名で2個減らしてくっつけ直す array_pop( $temp_oya ); array_pop( $temp_oya ); // implodeするとき、/だけだと消えるので if( count( $temp_oya ) == 1 ){ $dir_oya = '/'; } else { $dir_oya = implode( "/", $temp_oya ); } } // 値があった場合はそれを使用 } else { $dir_oya = $vdir_target; } // dir_oya が有ると言うことはまだ上があるってことだ if ( $dir_oya ) { $oya = get_vd( $dir_oya, NULL, $loop + 1 ); foreach( $oya as $value ) { $result[ $value['depth'] ] = $value; } } // 値に現在の値を代入 // roopが0の時はその場所なのでリンクは不要 // ファイルがないときもリンクは無し if( $loop != 0 && file_exists( $_SERVER['DOCUMENT_ROOT'] . $target ) ){ if( basename( $target, '.xml' ) == 'index' ) { $target = preg_replace( "/^(.*\/).+?$/i", '$1', $target ); } $result[ $loop ] = array( 'path' => $target, 'subject' => $title_target, 'depth' => $loop ); } else { $result[ $loop ] = array( 'path' => '', 'subject' => $title_target, 'depth' => $loop ); } return $result; } // エラーファンクション function exit_with_xml( $msg, $code = "" ) { $mode = "with_xml"; $info = array(); $with_xml = << END_XML; $info['entity'] = "/error/"; $info['id'] = "/error/"; $info['with_xml'] = $with_xml; $info['components'] = array(); if( $code == 404 ) { header( "HTTP/1.0 404 Not Found" ); } lemmih( $mode, $info ); exit(); } function eval_buffer( $string ) { ob_start(); eval( "$string[1]" ); $result = ob_get_contents(); ob_end_clean(); return $result; } //------------------------------------------------------------------------- // array parse_http_date( string Date ) // DateはRFC1123、RFC 850、ANSI C's asctime() formatのいずれか。 //------------------------------------------------------------------------- function parse_http_date( $string_date ) { // 月の名前と数字を定義 $define_month = array( 01 => "Jan", 02 => "Feb", 03 => "Mar", 04 => "Apr", 05 => "May", 06 => "Jun", 07 => "Jul", 08 => "Aug", 09 => "Sep", 10 => "Oct", 11 => "Nov", 12 => "Dec" ); if( preg_match( "/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), ([0-3][0-9]) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-9]{4}) ([0-2][0-9]):([0-5][0-9]):([0-5][0-9]) GMT$/", $string_date, $temp_date ) ) { $date["hour"] = $temp_date[5]; $date["minute"] = $temp_date[6]; $date["second"] = $temp_date[7]; // 定義済みの月の名前を数字に変換する $date["month"] = array_search( $temp_date[3], $define_month ); $date["day"] = $temp_date[2]; $date["year"] = $temp_date[4]; } elseif( preg_match( "/^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), ([0-3][0-9])-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-([0-9]{2}) ([0-2][0-9]):([0-5][0-9]):([0-5][0-9]) GMT$/", $string_date, $temp_date ) ) { $date["hour"] = $temp_date[5]; $date["minute"] = $temp_date[6]; $date["second"] = $temp_date[7]; // 定義済みの月の名前を数字に変換する $date["month"] = array_search( $temp_date[3], $define_month ); // 年が2桁しかないので1900を足して4桁に $date["day"] = $temp_date[2]; $date["year"] = 1900 + $temp_date[4]; } elseif( preg_match( "/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ([0-3 ][0-9]) ([0-2][0-9]):([0-5][0-9]):([0-5][0-9]) ([0-9]{4})$/", $string_date, $temp_date ) ) { $date["hour"] = $temp_date[4]; $date["minute"] = $temp_date[5]; $date["second"] = $temp_date[6]; $date["month"] = array_search( $temp_date[2], $define_month ); // 日が1桁の場合先、半角スペースを0に置換 $date["day"] = str_replace( " ", 0, $temp_date[3] ); // 定義済みの月の名前を数字に変換する $date["year"] = $temp_date[7]; } else { return FALSE; } // UNIXタイムスタンプを生成GMTなのに注意 $date["timestamp"] = gmmktime( $date["hour"], $date["minute"], $date["second"], $date["month"], $date["day"], $date["year"] ); return $date; } //------------------------------------------------------------------------- // string relative_str( string base [, int distance, bool overflow ]] ) // baseは任意の文字列。distanceは移動距離、overflowは桁溢れに対応するか。 // 省略された場合、それぞれ1、TRUEが初期値になります。 //------------------------------------------------------------------------- function relative_str( $str_base, $distance = 1, $option = TRUE ) { // 文字列を数値に変換して距離を足し、条件に合わせて戻り値を返す $num_base = str_to_num( $str_base ); $num_target = $num_base + $distance; if( $str_target = num_to_str( $num_target ) ) { if( ! $option && strlen( $str_target ) > strlen( $str_base ) ) { return FALSE; } else { return $str_target; } } else { return FALSE; } } //------------------------------------------------------------------------- // int str_to_num( string code ) // codeは任意の文字列。引数が扱えない値の場合FALSEを返します。 //------------------------------------------------------------------------- function str_to_num( $target ) { // アルファベットの定義 $alphabet = array( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ); // 変数の方を調べて不正な値を弾く if( ! is_string( $target ) || $target == "" ) { return FALSE; } $length = strlen( $target ); for( $i = 1; $i <= $length; $i++ ) { // 末尾の1桁を取り出して $one = substr( $target, - $i, 1 ); // 数字に変換。この時aが0から始まることに注意 $num = array_search( $one, $alphabet ); if( $i == 1 ) { // 1桁目はa=0なのでそのまま $result = $num; } else { // 2桁目以降はa=1なので1足してから桁を掛ける $result += ( $num + 1 ) * pow( 26, $i - 1 ); } } return $result; } //------------------------------------------------------------------------- // string num_to_str( int number ) // numberは任意の整数。 //------------------------------------------------------------------------- function num_to_str( $target ) { // アルファベットの定義 $alphabet = array( "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", ); // 不正な引数を弾く。負の値は無効。 if( ! is_numeric( $target ) || $target < 0 ) { return FALSE; } // まず、1桁目。a=0なのでそのままmodを求める $one = fmod( $target , 26 ); $result = $alphabet[ $one ]; // 1桁目を引いた余りから繰り上がり分を求める $carry = ( $target - $one ) / 26; // 繰り上がりが無くなるまで繰り返し while( $carry != 0 ) { // a=1なので1引いてからmodを求める。 $one = fmod( $carry - 1 , 26 ); $result = $alphabet[ $one ] . $result; $carry = ( $carry - 1 - $one ) / 26; } return $result; } ?>