svnno****@sourc*****
svnno****@sourc*****
2010年 1月 10日 (日) 15:52:28 JST
Revision: 768 http://sourceforge.jp/projects/p2-php/svn/view?view=rev&revision=768 Author: rsk Date: 2010-01-10 15:52:28 +0900 (Sun, 10 Jan 2010) Log Message: ----------- expack: - magic_quotes_gpc = On, mbstring.encoding_translation = On ã®ç°å¢ã§ã¯åä½ããªãããã«ããã - mbstring.encoding_translation ãèæ ®ããªãããã«ãªã£ãã®ã§ å ¥åã¨ã³ã³ã¼ãã£ã³ã°ã®åè£ããCP51932 (EUC-JP)ãé¤å¤ããã - ãã«ãã¤ãã¢ã¿ãã¯ããã³ã¹ã¯ãªããã¤ã³ã¸ã§ã¯ã·ã§ã³å¯¾çã å³æ ¼åããã Modified Paths: -------------- p2ex/trunk/conf/conf.inc.php p2ex/trunk/edit_user_font.php p2ex/trunk/ic2.php p2ex/trunk/ic2_getter.php p2ex/trunk/iv2.php p2ex/trunk/lib/bootstrap.php p2ex/trunk/lib/conf_user_updater.inc.php p2ex/trunk/lib/fontconfig.inc.php p2ex/trunk/lib/p2util.inc.php -------------- next part -------------- Modified: p2ex/trunk/conf/conf.inc.php =================================================================== --- p2ex/trunk/conf/conf.inc.php 2010-01-09 16:57:35 UTC (rev 767) +++ p2ex/trunk/conf/conf.inc.php 2010-01-10 06:52:28 UTC (rev 768) @@ -116,19 +116,14 @@ // ©®tbV ðItÉ·é ob_implicit_flush(0); - // NCAg©çÚ±ðØçêÄàð±s·é - // ignore_user_abort(1); - // file($filename, FILE_IGNORE_NEW_LINES) Å CR/LF/CR+LF Ì¢¸êàsƵĵ¤ ini_set('auto_detect_line_endings', 1); - // session.trans_sidLø â output_add_rewrite_var(), http_build_query() Ŷ¬EÏX³êé + // session.trans_sidLø â output_add_rewrite_var(), + // http_build_query() Ŷ¬EÏX³êé // URLÌGETp[^æØè¶(ñ)ð"&"É·éBiftHgÍ"&"j ini_set('arg_separator.output', '&'); - // NGXgIDðÝè (RXgªå«¢ÉgÁĢȢÌÅp~) - //define('P2_REQUEST_ID', substr($_SERVER['REQUEST_METHOD'], 0, 1) . md5(serialize($_REQUEST))); - // Windows Èç if (strncasecmp(PHP_OS, 'WIN', 3) == 0) { // Windows @@ -144,7 +139,9 @@ $DIR_SEP = DIRECTORY_SEPARATOR; $PATH_SEP = PATH_SEPARATOR; - // mbstring.script_encoding = SJIS-win ¾Æ "\0", "\x00" È~ªJbg³êéÌÅ + // koCgè + // mbstring.script_encoding = SJIS-win ¾Æ + // "\0", "\x00" È~ªJbg³êéÌÅAchr()Öðg¤ define('P2_NULLBYTE', chr(0)); // }}} @@ -229,8 +226,8 @@ require 'Benchmark/Profiler.php'; } $profiler = new Benchmark_Profiler(true); - // print_memory_usage(); - register_shutdown_function('print_memory_usage'); + // p2_print_memory_usage(); + register_shutdown_function('p2_print_memory_usage'); } // }}} @@ -388,13 +385,17 @@ p2die('Z[t[hÅ®ì·éPHPÅÍg¦Ü¹ñB'); } - // register_globals - if (ini_get('register_globals')) { - $msg = <<<EOP -\úµÈ¢®ìðð¯é½ßÉ php.ini Å register_globals ð Off ɵľ³¢B -magic_quotes_gpc â mbstring.encoding_translation à Off ɳêé±Æ𨷷ߵܷB -EOP; - p2die('register_globals ª On Å·B', $msg); + // register_globals, magic_quotes_gpc, mbstring.encoding_translation + $directives = array( + 'register_globals', + 'magic_quotes_gpc', + 'mbstring.encoding_translation', + ); + foreach ($directives as $directive) { + if (ini_get($directive)) { + p2die("{$directive} ª On Å·B", + "php.ini Å {$directive} ð Off ɵľ³¢B"); + } } // eAccelerator Modified: p2ex/trunk/edit_user_font.php =================================================================== --- p2ex/trunk/edit_user_font.php 2010-01-09 16:57:35 UTC (rev 767) +++ p2ex/trunk/edit_user_font.php 2010-01-10 06:52:28 UTC (rev 768) @@ -37,7 +37,7 @@ $controllerObject = (object)array( 'fontconfig_types' => $fontconfig_types, 'fontconfig_params' => $fontconfig_params, - 'skindata' => fontconfig_load_skin_setting(), + 'skindata' => p2_fontconfig_load_skin_setting(), 'safari' => 0, 'mac' => false, ); @@ -57,7 +57,7 @@ // Mac ÍuEUÉæÁĶÌ_Oʪå«Ïíè // »ÌíÞà»±»±½¢ÌÅ»ÝÌuEUÉ}b`µÈ¢àÌðB· $ft = &$controllerObject->fontconfig_types; -$type = fontconfig_detect_agent(); +$type = p2_fontconfig_detect_agent(); switch ($type) { case 'safari3': $controllerObject->safari = 3; @@ -182,7 +182,7 @@ } } if ($updated_fontconfig['enabled']) { - fontconfig_apply_custom(); + p2_fontconfig_apply_custom(); } else { $skin_en = preg_replace('/&_=[^&]*/', '', $skin_en) . '&_=' . rawurlencode($skin_uniq); } @@ -193,12 +193,12 @@ // oÍ $flexy->outputObject($controllerObject, $elements); -// {{{ fontconfig_load_skin_setting() +// {{{ p2_fontconfig_load_skin_setting() /** * JX^ÝèÅ㫳êĢȢXLÝèðÇÝÞ */ -function fontconfig_load_skin_setting() +function p2_fontconfig_load_skin_setting() { global $_conf, $STYLE; @@ -207,17 +207,17 @@ $fontfamily = (isset($STYLE['fontfamily.orig'])) ? $STYLE['fontfamily.orig'] : ((isset($STYLE['fontfamily'])) ? $STYLE['fontfamily'] : ''); - $skindata['fontfamily'] = fontconfig_implode_fonts($fontfamily); + $skindata['fontfamily'] = p2_fontconfig_implode_fonts($fontfamily); $fontfamily_bold = (isset($STYLE['fontfamily_bold.orig'])) ? $STYLE['fontfamily_bold.orig'] : ((isset($STYLE['fontfamily_bold'])) ? $STYLE['fontfamily_bold'] : ''); - $skindata['fontfamily_bold'] = fontconfig_implode_fonts($fontfamily_bold); + $skindata['fontfamily_bold'] = p2_fontconfig_implode_fonts($fontfamily_bold); $fontfamily_aa = (isset($_conf['expack.am.fontfamily.orig'])) ? $_conf['expack.am.fontfamily.orig'] : ((isset($_conf['expack.am.fontfamily'])) ? $_conf['expack.am.fontfamily'] : ''); - $skindata['fontfamily_aa'] = fontconfig_implode_fonts($fontfamily_aa); + $skindata['fontfamily_aa'] = p2_fontconfig_implode_fonts($fontfamily_aa); $normal = ($skindata['fontfamily_bold'] == '') ? '' : 'normal'; @@ -235,20 +235,20 @@ } // }}} -// {{{ fontconfig_implode_fonts() +// {{{ p2_fontconfig_implode_fonts() -function fontconfig_implode_fonts($fonts) +function p2_fontconfig_implode_fonts($fonts) { if (!is_array($fonts)) { $fonts = explode(',', (string)$fonts); } - return '"' . implode('","', array_map('fontconfig_trim', $fonts)) . '"'; + return '"' . implode('","', array_map('p2_fontconfig_trim', $fonts)) . '"'; } // }}} -// {{{ fontconfig_trim() +// {{{ p2_fontconfig_trim() -function fontconfig_trim($str) +function p2_fontconfig_trim($str) { return trim($str, " \r\n\t\x0B\"'" . P2_NULLBYTE); } Modified: p2ex/trunk/ic2.php =================================================================== --- p2ex/trunk/ic2.php 2010-01-09 16:57:35 UTC (rev 767) +++ p2ex/trunk/ic2.php 2010-01-10 06:52:28 UTC (rev 768) @@ -715,14 +715,6 @@ require 'HTML/QuickForm/Renderer/ObjectFlexy.php'; } - // conf.inc.phpÅêstripslashes()µÄ¢é¯ÇAHTML_QuickFormÅàÆ©Éstripslashes()·éÌÅB - // oOÌ·°ÆÈéÂ\«àÛèÅ«È¢EEE - if (get_magic_quotes_gpc()) { - $_GET = array_map('addslashes_r', $_GET); - $_POST = array_map('addslashes_r', $_POST); - $_REQUEST = array_map('addslashes_r', $_REQUEST); - } - if (isset($uri)) { $img_o = 'uri'; $img_p = $uri; Modified: p2ex/trunk/ic2_getter.php =================================================================== --- p2ex/trunk/ic2_getter.php 2010-01-09 16:57:35 UTC (rev 767) +++ p2ex/trunk/ic2_getter.php 2010-01-10 06:52:28 UTC (rev 768) @@ -18,14 +18,6 @@ // }}} // {{{ ú» -// conf.inc.phpÅêstripslashes()µÄ¢é¯ÇAHTML_QuickFormÅàÆ©Éstripslashes()·éÌÅB -// oOÌ·°ÆÈéÂ\«àÛèÅ«È¢EEE -if (get_magic_quotes_gpc()) { - $_GET = array_map('addslashes_r', $_GET); - $_POST = array_map('addslashes_r', $_POST); - $_REQUEST = array_map('addslashes_r', $_REQUEST); -} - // CuÇÝÝ require_once 'HTML/QuickForm.php'; require_once 'HTML/QuickForm/Renderer/ObjectFlexy.php'; Modified: p2ex/trunk/iv2.php =================================================================== --- p2ex/trunk/iv2.php 2010-01-09 16:57:35 UTC (rev 767) +++ p2ex/trunk/iv2.php 2010-01-10 06:52:28 UTC (rev 768) @@ -236,14 +236,6 @@ // }}} // {{{ prepare (Form & Template) -// conf.inc.phpÅêstripslashes()µÄ¢é¯ÇAHTML_QuickFormÅàÆ©Éstripslashes()·éÌÅB -// oOÌ·°ÆÈéÂ\«àÛèÅ«È¢EEE -if (get_magic_quotes_gpc()) { - $_GET = array_map('addslashes_r', $_GET); - $_POST = array_map('addslashes_r', $_POST); - $_REQUEST = array_map('addslashes_r', $_REQUEST); -} - // y[WJÚptH[ðÝè // y[WJÚÍGETÅs¤ªAæîñÌXVÍPOSTÅs¤ÌÅÇ¿çÅàó¯üêéæ¤É·é // i_OOÉ $qf->updateAttributes(array('method' => 'get')); Æ·éj Modified: p2ex/trunk/lib/bootstrap.php =================================================================== --- p2ex/trunk/lib/bootstrap.php 2010-01-09 16:57:35 UTC (rev 767) +++ p2ex/trunk/lib/bootstrap.php 2010-01-10 06:52:28 UTC (rev 768) @@ -4,10 +4,16 @@ * conf/conf.inc.php Ì p2configure() ©çÇÝÜêéB */ +require_once 'Net/UserAgent/Mobile.php'; +require_once $P2_LIB_DIR_S . 'Session.php'; +require_once $P2_LIB_DIR_S . 'Login.php'; + // {{{ zXg`FbN if ($_conf['secure']['auth_host'] || $_conf['secure']['auth_bbq']) { - require_once $P2_LIB_DIR_S . 'HostCheck.php'; + if (!class_exists('HostCheck', false)) { + include $P2_LIB_DIR_S . 'HostCheck.php'; + } if (($_conf['secure']['auth_host'] && HostCheck::getHostAuth() == false) || ($_conf['secure']['auth_bbq'] && HostCheck::getHostBurned() == true) ) { @@ -24,7 +30,7 @@ } /** - * NGXgÏðêÅNH[g¶R[hÏ· + * NGXgÏÌØƶR[hÏ· * * ú{êðüÍ·éÂ\«Ì étH[ÉÍBµvfÅ * GR[fBO»èp̶ñðdñÅ¢é @@ -32,48 +38,46 @@ * $_COOKIE Í $_REQUEST ÉÜßÈ¢ */ if (!empty($_GET) || !empty($_POST)) { - if (isset($_REQUEST['_hint'])) { - // "CP932" Í "SJIS-win" ÌGCAXÅA"SJIS-win" Æ "SJIS" Íʨ - // "CP51932", "eucJP-win", "EUC-JP" Í»ê¼êʨ (libmbflIÈÓ¡Å) - $request_encoding = mb_detect_encoding($_REQUEST['_hint'], 'UTF-8,CP51932,CP932'); - if ($request_encoding == 'SJIS-win') { - $request_encoding = false; + $hint = null; + + // NULLoCgA^bNÆXNvgCWFNVÌØA + // GR[fBO»èp¶ñÌæ¾ + if (!empty($_GET)) { + array_walk_recursive($_GET, 'p2_scan_nullbyte'); + p2_scan_script_injection($_GET); + if (array_key_exists('_hint', $_GET)) { + $hint = $_GET['_hint']; } - } else { - $request_encoding = 'UTF-8,CP51932,CP932'; } + if (!empty($_POST)) { + array_walk_recursive($_POST, 'p2_scan_nullbyte'); + p2_scan_script_injection($_POST); + if (array_key_exists('_hint', $_POST)) { + $hint = $_POST['_hint']; + } + } - if (get_magic_quotes_gpc()) { - $_GET = array_map('stripslashes_r', $_GET); - $_POST = array_map('stripslashes_r', $_POST); + // GR[fBO»è + if ($hint) { + $request_encoding = mb_detect_encoding($hint, 'ASCII,UTF-8,SJIS-win'); + if (!strcasecmp($request_encoding, 'ASCII')) { + p2die('s³ÈGR[fBO»èqgÅ·B'); + } + } else { + $request_encoding = 'ASCII,UTF-8,SJIS-win'; } - if ($request_encoding) { - mb_convert_variables('CP932', $request_encoding, $_GET, $_POST); + // UTF-8ÈçShift_JISÉÏ· + if (!strcasecmp($request_encoding, 'UTF-8')) { + mb_convert_variables('SJIS-win', 'UTF-8', $_GET, $_POST); } + // $_REQUEST ðÄ\¬ if ($_SERVER['REQUEST_METHOD'] == 'POST') { - $_POST = array_map('nullfilter_r', $_POST); - if (count($_GET)) { - $_GET = array_map('nullfilter_r', $_GET); - $_REQUEST = array_merge($_GET, $_POST); - } else { - $_REQUEST = $_POST; - } + $_REQUEST = array_merge($_GET, $_POST); } else { - $_GET = array_map('nullfilter_r', $_GET); $_REQUEST = $_GET; } - - // ÈÕXNvgCWFNVÎô - foreach (array('host', 'bbs', 'key', 'ls') as $_k) { - if (array_key_exists($_k, $_REQUEST)) { - $_v = $_REQUEST[$_k]; - if (htmlspecialchars($_v, ENT_QUOTES) != $_v) { - p2die('NGXgp[^És³È¶ª èÜ·B'); - } - } - } } else { $_REQUEST = array(); } @@ -81,8 +85,6 @@ // }}} // {{{ [»è -require_once 'Net/UserAgent/Mobile.php'; - $_conf['ktai'] = false; $_conf['iphone'] = false; $_conf['input_type_search'] = false; @@ -249,12 +251,14 @@ filemtime($P2_CONF_DIR_S . 'conf_user_def_i.inc.php') > $conf_user_mtime) { // ftHgÝèðÇÝÞ - require_once $P2_CONF_DIR_S . 'conf_user_def.inc.php'; + include $P2_CONF_DIR_S . 'conf_user_def.inc.php'; // ÝèÌXV if (!array_key_exists('mobile.link_youtube', $conf_user)) { - require_once $P2_LIB_DIR_S . 'conf_user_updater.inc.php'; - $conf_user = conf_user_update_080908($conf_user); + if (!function_exists('p2_conf_user_update_080908')) { + include $P2_LIB_DIR_S . 'conf_user_updater.inc.php'; + } + $conf_user = p2_conf_user_update_080908($conf_user); } $_conf = array_merge($_conf, $conf_user_def, $conf_user); @@ -276,7 +280,7 @@ unset($cont, $conf_user); } else { // ftHgÝèðÇÝÞ - require_once $P2_CONF_DIR_S . 'conf_user_def.inc.php'; + include $P2_CONF_DIR_S . 'conf_user_def.inc.php'; $_conf = array_merge($_conf, $conf_user_def); } @@ -391,7 +395,9 @@ } if (!$_conf['ktai']) { - require_once $P2_LIB_DIR_S . 'fontconfig.inc.php'; + if (!function_exists('p2_fontconfig_apply_custom')) { + include $P2_LIB_DIR_S . 'fontconfig.inc.php'; + } if ($_conf['expack.am.enabled']) { $_conf['expack.am.fontfamily'] = p2_correct_css_fontfamily($_conf['expack.am.fontfamily']); @@ -400,7 +406,7 @@ } } - fontconfig_apply_custom(); + p2_fontconfig_apply_custom(); } // }}} @@ -525,7 +531,9 @@ switch ($_conf['mobile.display_accesskey']) { case 2: - require_once $P2_LIB_DIR_S . 'emoji.inc.php'; + if (!function_exists('p2_get_emoji')) { + include $P2_LIB_DIR_S . 'emoji.inc.php'; + } $emoji = p2_get_emoji($mobile); //$emoji = p2_get_emoji(Net_UserAgent_Mobile::factory('KDDI-SA31 UP.Browser/6.2.0.7.3.129 (GUI) MMP/2.0')); $_conf['k_accesskey_st'] = array( @@ -630,8 +638,6 @@ $_conf['sid_at_a'] = ''; -require_once $P2_LIB_DIR_S . 'Session.php'; - // {{{ ZbVf[^Û¶fBNgð`FbN if ($_conf['session_save'] == 'p2' and session_module_name() == 'files') { @@ -691,7 +697,6 @@ } // OCNXÌCX^X¶¬iOC[Uªwè³êĢȯêÎA±Ì_ÅOCtH[\¦Éj -require_once $P2_LIB_DIR_S . 'Login.php'; $_login = new Login(); // }}} Modified: p2ex/trunk/lib/conf_user_updater.inc.php =================================================================== --- p2ex/trunk/lib/conf_user_updater.inc.php 2010-01-09 16:57:35 UTC (rev 767) +++ p2ex/trunk/lib/conf_user_updater.inc.php 2010-01-10 06:52:28 UTC (rev 768) @@ -3,7 +3,7 @@ * rep2expack - [UÝèÚsx */ -// {{{ conf_user_update_080908() +// {{{ p2_conf_user_update_080908() /** * 080908ÅgÑpÌÝèL[ðÏXµ½ÌÅAÝè©çÚs·é @@ -11,7 +11,7 @@ * @param array $old Ýè * @return array Vµ¢L[É«·¦çê½Ýè */ -function conf_user_update_080908(array $old) +function p2_conf_user_update_080908(array $old) { $map = array( 'k_sb_show_first' => 'mobile.sb_show_first', Modified: p2ex/trunk/lib/fontconfig.inc.php =================================================================== --- p2ex/trunk/lib/fontconfig.inc.php 2010-01-09 16:57:35 UTC (rev 767) +++ p2ex/trunk/lib/fontconfig.inc.php 2010-01-10 06:52:28 UTC (rev 768) @@ -3,14 +3,14 @@ * rep2expack - JX^tHgÝèpÖQ */ -// {{{ fontconfig_detect_agent() +// {{{ p2_fontconfig_detect_agent() /** * tHgÝèpÉ[UG[WFgð»è·é * * @return string */ -function fontconfig_detect_agent($ua = null) +function p2_fontconfig_detect_agent($ua = null) { if ($ua === null) { $ua = $_SERVER['HTTP_USER_AGENT']; @@ -38,14 +38,14 @@ } // }}} -// {{{ fontconfig_apply_custom() +// {{{ p2_fontconfig_apply_custom() /** * tHgÝèðÇÝÞ * * @return void */ -function fontconfig_apply_custom() +function p2_fontconfig_apply_custom() { global $STYLE, $_conf, $skin_en, $skin_uniq; @@ -65,7 +65,7 @@ $current_fontconfig = array('enabled' => false, 'custom' => array()); } - $type = fontconfig_detect_agent(); + $type = p2_fontconfig_detect_agent(); if ($current_fontconfig['enabled'] && is_array($current_fontconfig['custom'][$type])) { $skin_uniq = P2_VERSION_ID . sprintf('.%u', crc32($fontconfig_data)); Modified: p2ex/trunk/lib/p2util.inc.php =================================================================== --- p2ex/trunk/lib/p2util.inc.php 2010-01-09 16:57:35 UTC (rev 767) +++ p2ex/trunk/lib/p2util.inc.php 2010-01-10 06:52:28 UTC (rev 768) @@ -202,92 +202,54 @@ } // }}} -// {{{ stripslashes_r() +// {{{ p2_scan_nullbyte() /** - * ÄAIÉstripslashesð©¯é - * GET/POST/COOKIEÏpÈÌÅIuWFNgÌvpeBÉÍεȢ + * NGXgp[^©çNULLoCgðoµ½çI¹·é + * array_walk_recursive() pR[obNÖ * - * @param array|string $var - * @param int $r - * @return array|string + * @param mixed $value + * @param mixed $key + * @return void */ -function stripslashes_r($var, $r = 0) +function p2_scan_nullbyte($value, $key) { - if (is_array($var)) { - if ($r < 3) { - $r++; - foreach ($var as $key => $value) { - $var[$key] = stripslashes_r($value, $r); - } - } /* else { p2die("too deep multi dimentional array given."); } */ - } elseif (is_string($var)) { - $var = stripslashes($var); + if (is_string($value) && strpos($value, P2_NULLBYTE) !== false) { + p2die('NGXgp[^ÉNULLoCgªÜÜêĢܷB'); } - return $var; } // }}} -// {{{ addslashes_r() +// {{{ p2_scan_script_injection() /** - * ÄAIÉaddslashesð©¯é + * ¶ÌÜÜHTMLÉßÜêé host, bbs, key, ls É + * HTMLÌÁ궪ÜÜêÄ¢½çI¹·é * - * @param array|string $var - * @param int $r - * @return array|string + * @param array $request + * @return void */ -function addslashes_r($var, $r = 0) +function p2_scan_script_injection($request) { - if (is_array($var)) { - if ($r < 3) { - $r++; - foreach ($var as $key => $value) { - $var[$key] = addslashes_r($value, $r); + foreach (array('host', 'bbs', 'key', 'ls') as $key) { + if (array_key_exists($key, $request)) { + $value = $request[$key]; + if (htmlspecialchars($value, ENT_QUOTES) != $value) { + p2die('NGXgp[^És³È¶ª èÜ·B'); } - } /* else { p2die("too deep multi dimentional array given."); } */ - } elseif (is_string($var)) { - $var = addslashes($var); + } } - return $var; } // }}} -// {{{ nullfilter_r() +// {{{ p2_print_memory_usage() /** - * ÄAIÉk¶ðí·é - * - * NULLoCgA^bNÎô - * - * @param array|string $var - * @param int $r - * @return array|string - */ -function nullfilter_r($var, $r = 0) -{ - if (is_array($var)) { - if ($r < 3) { - $r++; - foreach ($var as $key => $value) { - $var[$key] = nullfilter_r($value, $r); - } - } /* else { p2die("too deep multi dimentional array given."); } */ - } elseif (is_string($var)) { - $var = str_replace(P2_NULLBYTE, '', $var); - } - return $var; -} - -// }}} -// {{{ print_memory_usage() - -/** * ÌgpÊð\¦·é * * @return void */ -function print_memory_usage() +function p2_print_memory_usage() { if (function_exists('memory_get_usage')) { $usage = memory_get_usage(); @@ -621,26 +583,7 @@ } // }}} -// {{{ json_encode() -if (!extension_loaded('json')) { - /** - * jsonGNXeVÌjson_encode()ÖðPEARÌServices_JSONÅãÖ·é - * - * @param mixed $value - * @return string - */ - function json_encode($value) { - if (!class_exists('Services_JSON', false)) { - include 'Services/JSON.php'; - } - $json = new Services_JSON(); - return $json->encodeUnsafe($value); - } -} - -// }}} - /* * Local Variables: * mode: php