/** * constructor * * @param string $path_homedir Pickles のホームディレクトリのパス */ public function __construct($path_homedir) { // initialize PHP if (!extension_loaded('mbstring')) { trigger_error('mbstring not loaded.'); } if (is_callable('mb_internal_encoding')) { mb_internal_encoding('UTF-8'); @ini_set('mbstring.internal_encoding', 'UTF-8'); @ini_set('mbstring.http_input', 'UTF-8'); @ini_set('mbstring.http_output', 'UTF-8'); } @ini_set('default_charset', 'UTF-8'); if (is_callable('mb_detect_order')) { @ini_set('mbstring.detect_order', 'UTF-8,SJIS-win,eucJP-win,SJIS,EUC-JP,JIS,ASCII'); mb_detect_order('UTF-8,SJIS-win,eucJP-win,SJIS,EUC-JP,JIS,ASCII'); } @header_remove('X-Powered-By'); $this->set_status(200); // 200 OK if (!array_key_exists('REMOTE_ADDR', $_SERVER)) { // commandline only if (realpath($_SERVER['SCRIPT_FILENAME']) === false || dirname(realpath($_SERVER['SCRIPT_FILENAME'])) !== realpath('./')) { if (array_key_exists('PWD', $_SERVER) && is_file($_SERVER['PWD'] . '/' . $_SERVER['SCRIPT_FILENAME'])) { $_SERVER['SCRIPT_FILENAME'] = realpath($_SERVER['PWD'] . '/' . $_SERVER['SCRIPT_FILENAME']); } else { // for Windows // .px_execute.php で chdir(__DIR__) されていることが前提。 $_SERVER['SCRIPT_FILENAME'] = realpath('./' . basename($_SERVER['SCRIPT_FILENAME'])); } } } // load Config $this->path_homedir = $path_homedir; if (is_file($this->path_homedir . DIRECTORY_SEPARATOR . 'config.json')) { $this->conf = json_decode(file_get_contents($this->path_homedir . DIRECTORY_SEPARATOR . 'config.json')); } elseif (is_file($this->path_homedir . DIRECTORY_SEPARATOR . 'config.php')) { $this->conf = (include $this->path_homedir . DIRECTORY_SEPARATOR . 'config.php'); } $this->conf = json_decode(json_encode($this->conf)); if (!@is_array($this->conf->paths_enable_sitemap)) { // sitemap のロードを有効にするべきパス。 $this->conf->paths_enable_sitemap = array('*.html', '*.htm'); } if (@strlen($this->conf->default_timezone)) { @date_default_timezone_set($this->conf->default_timezone); } if (!@strlen($this->conf->path_files)) { $this->conf->path_files = '{$dirname}/{$filename}_files/'; } if (!@strlen($this->conf->copyright)) { // NOTE: 2016-03-15 $conf->copyright 追加 // 古い環境で Notice レベルのエラーが出る可能性があることを考慮し、初期化する。 $this->conf->copyright = null; } // make instance $bowl require_once __DIR__ . '/bowl.php'; $this->bowl = new bowl(); // Apply command-line option "--command-php" $req = new \tomk79\request(); if (strlen(@$req->get_cli_option('--command-php'))) { @($this->conf->commands->php = $req->get_cli_option('--command-php')); } if (strlen(@$req->get_cli_option('-c'))) { @($this->conf->path_phpini = $req->get_cli_option('-c')); } // make instance $fs $conf = new \stdClass(); $conf->file_default_permission = $this->conf->file_default_permission; $conf->dir_default_permission = $this->conf->dir_default_permission; $conf->filesystem_encoding = $this->conf->filesystem_encoding; $this->fs = new \tomk79\filesystem($conf); $this->path_homedir = $this->fs->get_realpath($this->path_homedir . '/'); // make instance $req $conf = new \stdClass(); $conf->session_name = $this->conf->session_name; $conf->session_expire = $this->conf->session_expire; $conf->directory_index_primary = $this->get_directory_index_primary(); $this->req = new \tomk79\request($conf); if (strlen(@$this->req->get_cli_option('-u'))) { $_SERVER['HTTP_USER_AGENT'] = @$this->req->get_cli_option('-u'); } // 公開キャッシュフォルダが存在しない場合、作成する if (strlen(@$this->conf->public_cache_dir) && !@is_dir('./' . $this->conf->public_cache_dir)) { $this->fs->mkdir('./' . $this->conf->public_cache_dir); } // _sysフォルダが存在しない場合、作成する foreach (array('/_sys/', '/_sys/ram/', '/_sys/ram/applock/', '/_sys/ram/caches/', '/_sys/ram/data/', '/_sys/ram/publish/') as $tmp_path_sys_dir) { if (strlen($this->path_homedir . $tmp_path_sys_dir) && !@is_dir($this->path_homedir . $tmp_path_sys_dir)) { $this->fs->mkdir($this->path_homedir . $tmp_path_sys_dir); } } // 環境変数 $_SERVER['DOCUMENT_ROOT'] をセット // get_path_docroot() は、$conf, $fs を参照するので、 // これらの初期化の後が望ましい。 if (!array_key_exists('DOCUMENT_ROOT', $_SERVER) || !strlen(@$_SERVER['DOCUMENT_ROOT'])) { // commandline only $_SERVER['DOCUMENT_ROOT'] = $this->get_path_docroot(); $_SERVER['DOCUMENT_ROOT'] = realpath($_SERVER['DOCUMENT_ROOT']); } // デフォルトの Content-type を出力 $this->output_content_type(); // ignore されたコンテンツはこの段階で判断してレスポンスする $fnc_response_ignore = function ($px) { if ($px->is_ignore_path($px->req()->get_request_file_path())) { $px->set_status(403); // 403 Forbidden print 'ignored path'; exit; } return false; }; // pass 判定されたコンテンツはこの段階で判断してレスポンスする $fnc_response_pass = function ($px) { if ($px->get_path_proc_type($px->req()->get_request_file_path()) === 'pass') { if (!$px->fs()->is_file('./' . $px->req()->get_request_file_path())) { @header('Content-type: text/html;'); $px->set_status(404); // 404 NotFound $px->bowl()->send('<p>404 - File not found.</p>'); return true; } $src = $px->fs()->read_file('./' . $px->req()->get_request_file_path()); $px->bowl()->send($src); return true; } return false; }; $pxcmd = $this->get_px_command(); if (is_null($pxcmd) || !count($pxcmd)) { // PXコマンドが無効かつ ignore か pass の場合、 // この時点でレスポンスを返す。 if ($fnc_response_ignore($this)) { // ignore のレスポンス return; } if ($fnc_response_pass($this)) { // pass のレスポンス return; } } // make instance $pxcmd require_once __DIR__ . '/pxcmd.php'; $this->pxcmd = new pxcmd($this); // funcs: Before sitemap $this->fnc_call_plugin_funcs(@$this->conf->funcs->before_sitemap, $this); // make instance $site require_once __DIR__ . '/site.php'; $is_enable_sitemap = $this->is_path_enable_sitemap($this->req()->get_request_file_path()); if ($is_enable_sitemap) { $this->site = new site($this); } else { $this->site = false; } // execute Content $this->path_content = $this->req()->get_request_file_path(); $ext = $this->get_path_proc_type($this->req()->get_request_file_path()); if ($ext !== 'direct' && $ext !== 'pass') { if ($is_enable_sitemap) { $current_page_info = $this->site()->get_page_info($this->req()->get_request_file_path()); $this->path_content = $current_page_info['content']; if (is_null($this->path_content)) { $this->path_content = $this->req()->get_request_file_path(); } unset($current_page_info); } } foreach (array_keys(get_object_vars($this->conf->funcs->processor)) as $tmp_ext) { if ($this->fs()->is_file('./' . $this->path_content . '.' . $tmp_ext)) { $ext = $tmp_ext; $this->path_content = $this->path_content . '.' . $tmp_ext; break; } } $this->proc_type = $ext; unset($ext); // funcs: Before contents $this->fnc_call_plugin_funcs(@$this->conf->funcs->before_content, $this); // PXコマンドが有効、かつ ignore か pass の場合、 // この時点でレスポンスを返す。 // ここまでの before sitemap, before contents でレスポンスされた場合は、ここは通らない。 if ($fnc_response_ignore($this)) { // ignore のレスポンス return; } if ($fnc_response_pass($this)) { // pass のレスポンス return; } // execute content self::exec_content($this); // funcs: process functions $this->fnc_call_plugin_funcs(@$this->conf->funcs->processor->{$this->proc_type}, $this); // funcs: Before output $this->fnc_call_plugin_funcs(@$this->conf->funcs->before_output, $this); }
<?php require_once __DIR__ . '/../../vendor/autoload.php'; $req = new \tomk79\request(); @ini_set('memory_limit', -1); @error_reporting(E_ERROR | E_PARSE); @ini_set('display_errors', 1); if (!extension_loaded('mbstring')) { trigger_error('mbstring not loaded.'); } if (is_callable('mb_internal_encoding')) { mb_internal_encoding('UTF-8'); @ini_set('mbstring.internal_encoding', 'UTF-8'); @ini_set('mbstring.http_input', 'UTF-8'); @ini_set('mbstring.http_output', 'UTF-8'); } @ini_set('default_charset', 'UTF-8'); if (is_callable('mb_detect_order')) { @ini_set('mbstring.detect_order', 'UTF-8,SJIS-win,eucJP-win,SJIS,EUC-JP,JIS,ASCII'); mb_detect_order('UTF-8,SJIS-win,eucJP-win,SJIS,EUC-JP,JIS,ASCII'); } // var_dump($req->get_cli_options()); // var_dump($req->get_cli_option('--path')); $path_xlsx = $req->get_cli_option('--path'); $options = array('header_row' => $req->get_cli_option('--header_row'), 'header_col' => $req->get_cli_option('--header_col'), 'renderer' => $req->get_cli_option('--renderer'), 'cell_renderer' => $req->get_cli_option('--cell_renderer'), 'render_cell_width' => true, 'strip_table_tag' => true); // var_dump($path_xlsx); // var_dump($options); if (is_null($path_xlsx)) { print '<!-- ERROR: parameter path is required. -->'; exit; }
/** * directory traversal 対策 */ public function testDirectoryTraversal() { $conf = new stdClass(); $conf->server = $_SERVER; $conf->server['argv'] = array('/aaa/bbb/../'); $req = new tomk79\request($conf); $this->assertTrue($req->is_cmd()); $this->assertEquals($req->get_request_file_path(), '/aaa/index.html'); $conf = new stdClass(); $conf->server = $_SERVER; $conf->server['argv'] = array('/../../'); $req = new tomk79\request($conf); $this->assertEquals($req->get_request_file_path(), '/index.html'); $conf = new stdClass(); $conf->server = $_SERVER; $conf->server['argv'] = array('/test2/../../test.html'); $req = new tomk79\request($conf); $this->assertEquals($req->get_request_file_path(), '/test.html'); }