-<?php
-/*
- NP_SimpleURL : Improve url handling with a simple format.
-
- License
- -------
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- (see nucleus/documentation/index.html#license for more info)
-
- Usage
- -----
- Install this plugin and turn "FancyURLs mode" on.
-
- In index.php :
- Set absolute url (http://...) to $CONF['Self'].
- Set blog's shortname to $CONF['NP_SimpleURL']['selectBlog'] before including config.php. (optional)
- Set selectBlog('shortname') before selector(). (optional)
-
- In fancyurls.config.php or index.php :
- You can use some features (flags).
-
- $CONF['NP_SimpleURL']['UseAlias'] = 1; //convert id number to alias (shortname). don't turn "DropKeys" on if "UseAlias" is off.
- $CONF['NP_SimpleURL']['DropKeys'] = 1; //drop keys for blog, category and item
- $CONF['NP_SimpleURL']['ShowBlogAlways'] = 0; //show blog always
- $CONF['NP_SimpleURL']['ShowCategoryAlways'] = 1; //show category always (in permalink)
-
- 誤動作にハマらないために注意すべき事柄:
- 1.実在するディレクトリ名と同じ名前を、URL修飾キーやエイリアスに使わない。
- 2.スキンタイプ、URL修飾キーなどで予約済みの名前をエイリアスに使わない。
- 3.ブログ間で同名のカテゴリーエイリアスを使う場合は index.phpに $CONF['NP_SimpleURL']['selectBlog']をセットする。
- ※2の制約から解放されたい場合は DropKeys を無効にすること。
- ※3の制約は ShowBlogAlways を有効にしてURLにブログ情報を必ず含めることでも解消できる。
-
- History
- -------
- 2008-07-12 v0.21: Improve function for category alias. (yu)
- 2008-06-08 v0.2 : Add some new features. Support alias names. (yu)
- 2008-05-02 v0.1 : First release. (yu http://nucleus.datoka.jp/)
-*/
-
-
-/* ----------------- additional global functions ----------------- */
-
-/* addLinkParams()をグローバル関数として切り出せるように下記も一応グローバルで宣言しておく */
-
-if(!function_exists('getBlogURLFromID')) {
- function getBlogURLFromID($blogid)
- {
- static $buff;
-
- $blogid = (int)$blogid;
- if (!$buff[$blogid]) {
- $res = sql_query('SELECT bnumber, burl FROM ' . sql_table('blog'));
- if (mysql_num_rows($res)) {
- while ($data = mysql_fetch_assoc($res)) {
- $buff[ $data['bnumber'] ] = $data['burl'];
- }
- }
- }
- return $buff[$blogid];
- }
-}
-
-if(!function_exists('getBlogAliasFromID')) {
- function getBlogAliasFromID($id)
- {
- static $buff;
-
- $id = (int)$id;
- if (!$buff[$id]) {
- $buff[$id] = quickQuery('SELECT bshortname as result FROM ' . sql_table('blog') . ' WHERE bnumber=' . $id);
- }
- return ($buff[$id]) ? $buff[$id] : $id;
- }
-}
-
-if(!function_exists('getMemberAliasFromID')) {
- function getMemberAliasFromID($id)
- {
- static $buff;
-
- $id = (int)$id;
- if (!$buff[$id]) {
- $buff[$id] = quickQuery('SELECT mname as result FROM ' . sql_table('member') . ' WHERE mnumber=' . $id);
- $buff[$id] = str_replace(' ', '_', $buff[$id]);
- }
- return ($buff[$id]) ? $buff[$id] : $id;
- }
-}
-
-if(!function_exists('getCatAliasFromID')) {
- function getCatAliasFromID($id, $blogid)
- {
- global $manager;
- static $buff;
-
- $id = (int)$id;
- if (! isset($buff)) {
- $buff = getCatAliasesFromDB();
- }
- return ($buff[$blogid][$id]) ? $buff[$blogid][$id] : $id;
- }
-}
-
-if(!function_exists('getCatAliasesFromDB')) {
- function getCatAliasesFromDB()
- {
- $arr = array();
- $res = sql_query('SELECT catid, blogid, cshortname FROM ' . sql_table('plug_simpleurl') .' ORDER BY catid');
- while($data = mysql_fetch_assoc($res)) {
- $arr[ $data['blogid'] ][$data['catid']] = $data['cshortname'];
- }
- return $arr;
- }
-}
-
-if(!function_exists('getItemAliasFromID')) {
- function getItemAliasFromID($id)
- {
- global $manager;
-
- if ($manager->pluginInstalled('NP_SimpleURL')) {
- $obj =& $manager->getPlugin('NP_SimpleURL');
- $t = strip_tags($obj->_getDataFromItemID($id, $type='ititle'));
- $t = mb_substr(str_replace(array(' ','/','?','&','%'), '_', $t), 0, 20) .'-'. $id;
- return $t;
- }
- }
-}
-
-
-class NP_SimpleURL extends NucleusPlugin
-{
- function getName() { return 'Simple URL'; }
- function getAuthor() { return 'yu'; }
- function getURL() { return 'http://nucleus.datoka.jp/'; }
- function getVersion() { return '0.21'; }
- function getMinNucleusVersion() { return 322; }
- function supportsFeature($what) { return (int)($what == 'SqlTablePrefix'); }
- function hasAdminArea() { return 1; }
- function getDescription()
- {
- return 'Improve url handling with a simple format.';
- }
- function getEventList()
- {
- return array(
- 'PostAuthentication',
- 'ParseURL',
- 'GenerateURL',
- 'PostAddCategory',
- 'PostDeleteCategory',
- 'PostMoveCategory',
- 'QuickMenu'
- );
- }
-
- var $flg_fancy;
- var $arr_item;
-
- function install()
- {
- $this->createOption('flg_qmenu', 'Show on quick menu', 'yesno', 'yes');
- $this->createOption('flg_erase', 'Erase data on uninstallation', 'yesno', 'no');
-
- //テーブルが存在するかチェックする
- $chktable = sql_query("SHOW TABLES LIKE '". sql_table('plug_simpleurl') ."'");
- if (mysql_num_rows($chktable)) return;
-
- //存在しなければテーブル生成&データ代入
- sql_query("CREATE TABLE IF NOT EXISTS ". sql_table('plug_simpleurl') ." (
- catid INT UNSIGNED NOT NULL DEFAULT 0 PRIMARY KEY,
- blogid INT UNSIGNED NOT NULL DEFAULT 0,
- cshortname VARCHAR(50) NOT NULL DEFAULT '')");
- $res = sql_query("SELECT catid, cblog FROM ". sql_table('category'));
- while ($data = mysql_fetch_assoc($res)) {
- sql_query("INSERT ". sql_table('plug_simpleurl')
- ." SET catid=". $data['catid'] .", blogid=". $data['cblog'] .", cshortname='c". $data['catid'] ."'");
- }
- }
-
- function uninstall()
- {
- if ($this->getOption('flg_erase') == 'yes') {
- sql_query("DROP TABLE ". sql_table('plug_simpleurl'));
- }
- }
-
- function init()
- {
- global $CONF;
-
- $this->flg_fancy = ($CONF['URLMode'] == 'pathinfo');
-
- if ($this->flg_fancy) {
- //URLパラメータの並び順(あらかじめキーを作っておく)
- //外部プラグインは各々init()で$CONF['HogeKey']登録と、NP_SimpleURL::setURLOrder('hoge',N)する。
- $CONF['NP_SimpleURL']['URLOrder'] = array(
- $CONF['BlogKey'] => 0, //1番目
- $CONF['CategoryKey'] => 1, //2番目
- $CONF['SpecialskinKey'] => 2, //3番目
- $CONF['ArchiveKey'] => 10, //以下同順
- $CONF['ArchivesKey'] => 10,
- $CONF['ItemKey'] => 10,
- $CONF['MemberKey'] => 10,
- );
- }
- }
-
- /* ----------------- event methods ----------------- */
-
- function event_PostAuthentication(&$data)
- {
- //wake up! (nothing to do)
- //外部からNP_SimpleURLのメソッドを静的呼び出しするときの便宜を考えて。
- //NP_SimpleURL::addLinkParams()など
- }
-
- function event_QuickMenu(&$data)
- {
- global $member;
-
- if ($this->getOption('flg_qmenu') != 'yes') return;
- if (!$this->_canEdit()) return;
-
- array_push(
- $data['options'],
- array(
- 'title' => 'Simple URL',
- 'url' => $this->getAdminURL(),
- 'tooltip' => 'Setting of category alias'
- )
- );
- }
-
- function event_PostMoveCategory(&$data)
- {
- sql_query("UPDATE ". sql_table('plug_simpleurl')
- ." SET blogid=". $data['destblog']->getID() ." WHERE catid=". $data['catid']);
- }
-
- function event_PostAddCategory(&$data)
- {
- sql_query("INSERT ". sql_table('plug_simpleurl')
- ." SET catid=". $data['catid'] .", blogid=". $data['blog']->getID() .", cshortname='c". $data['catid'] ."'");
- }
-
- function event_PostDeleteCategory($data)
- {
- sql_query("DELETE ". sql_table('plug_simpleurl') ." WHERE catid=". $data['catid']);
- }
-
- //URLパース
- function event_ParseURL(&$pdata)
- {
- // nothing to do if another plugin already parsed the URL
- if ($pdata['complete']) return;
-
- global $CONF, $blogid, $catid, $itemid, $memberid, $archive, $archivelist;
-
- $complete =& $pdata['complete'];
- $virtualpath =& $pdata['info'];
- $virtualpath = preg_replace('/\.html$/', '', $virtualpath);
-
- //selectBlog()の先取り。URLパースのタイミング上、selectBlog()では遅いため。
- if (!$blogid and $CONF['SimpleURL']['selectBlog']) {
- selectBlog( $CONF['SimpleURL']['selectBlog'] );
- }
-
- $data = explode("/", $virtualpath );
- for ($i = 0; $i < sizeof($data); $i++) {
- switch ($data[$i]) {
- case $CONF['ItemKey']: // item/1 (itemid) or item/name (urlencoded ititle)
- $i++;
- if ($i < sizeof($data) ) {
- if (is_numeric($data[$i])) $itemid = intval($data[$i]);
- else $itemid = $this->_getItemIDFromAlias($data[$i]);
- }
- break;
-
- case $CONF['ArchivesKey']: // archives
- if ($blogid) {
- $archivelist = $blogid;
- }
- else {
- $archivelist = $CONF['DefaultBlog'];
- }
- break;
-
- case $CONF['ArchiveKey']: // archive/yyyy-mm
- $i++;
- if ($i < sizeof($data) ) {
- $archive = $data[$i];
- }
- break;
-
- case $CONF['BlogKey']: // blog/1 or blog/bshortname
- case 'blogid':
- $i++;
- if ($i < sizeof($data) ) {
- if (is_numeric($data[$i])) $blogid = intval($data[$i]);
- else $blogid = $this->_getBlogIDFromAlias($data[$i]);
- }
- break;
-
- case $CONF['CategoryKey']: // category/1 (catid) or category/aliasname
- case 'catid':
- $i++;
- if ($i < sizeof($data) ) {
- if (is_numeric($data[$i])) $catid = intval($data[$i]);
- else $catid = $this->_getCatIDFromAlias($data[$i]);
- }
- break;
-
- case $CONF['MemberKey']: // member/1 (memberid) or member/mname
- $i++;
- if ($i < sizeof($data) ) {
- if (is_numeric($data[$i])) $memberid = intval($data[$i]);
- else $memberid = $this->_getMemberIDFromAlias($data[$i]);
- }
- break;
-
- case $CONF['SpecialskinKey']: //extra/specialname
- $i++;
- if ($i < sizeof($data) ) {
- $_REQUEST['special'] = $data[$i];
- }
- break;
-
- default:
- //無効なキーは捨てる
- if ($data[$i] == '') break; //skip
-
- $flg_num = (is_numeric($data[$i]));
-
- //拡張キーと合致するかスキャンする
- $exkey = ucfirst($data[$i]) . 'Key';
- if (isset($CONF[$exkey])) {
- $exstore =& $_REQUEST; //代入先はリクエスト変数
-
- if (!$exstore[ $CONF[$exkey] ]) { //対象が未定義なら代入を許可する
- $i++;
- $exstore[ $CONF[$exkey] ] = $data[$i]; //そのまま代入してるので、利用時は値のチェックを忘れずに。
- }
- break;
- }
-
- //debuglog('check non-key val: '.$data[$i]);
- //「キー無し」の可能性をチェック。ここでは数値のみの値を避ける
- $tempid = 0;
- if ($CONF['NP_SimpleURL']['DropKeys'] and !$flg_num and preg_match('/^[0-9a-z_-]+$/', $data[$i])) {
- if (!$blog_done and $i == 0 and $CONF['NP_SimpleURL']['ShowBlogAlways']) { //ブログのキー無しは ShowBlogAlways が有効なときのみ
- $tempid = $this->_getBlogIDFromAlias($data[$i]);
- if ($tempid) {
- //debuglog('hit: blog'.$tempid. ' ' .$data[$i]);
- $blogid = $tempid;
- $blog_done = true;
- break;
- }
- //debuglog('through: blog '.$i);
- }
- if (!$cat_done and $i < 2) { //カテゴリーのキー無しの可能性をチェック
- $tempid = $this->_getCatIDFromAlias($data[$i]);
- if ($tempid) {
- //debuglog('hit: cat'.$tempid. ' ' .$data[$i]);
- $catid = $tempid;
- $cat_done = true;
- break;
- }
- //debuglog('through: cat '.$i);
- }
- }
- //アイテムのキー無しの可能性をチェック。数値のみも受け付ける(キー無し数値はアイテムとみなされる)
- if ($CONF['NP_SimpleURL']['DropKeys'] and !$item_done and
- (
- ($i >= 0 and !$CONF['NP_SimpleURL']['ShowBlogAlways']) or
- ($i >= 1 and $CONF['NP_SimpleURL']['ShowBlogAlways'] ^ $CONF['NP_SimpleURL']['ShowCategoryAlways']) or
- ($i >= 2 and $CONF['NP_SimpleURL']['ShowBlogAlways'] & $CONF['NP_SimpleURL']['ShowCategoryAlways'])
- )
- ) {
- if ($flg_num) $tempid = (int)$data[$i];
- else $tempid = $this->_getItemIDFromAlias($data[$i]);
-
- if ($tempid) {
- //debuglog('hit: item'.$tempid. ' ' .$data[$i]);
- $itemid = $tempid;
- $item_done = true;
- break;
- }
- //debuglog('through: item '.$i);
- }
- //debuglog('through: last '.$i);
- }
- }
- //debuglog(array('blogid'=>$blogid, 'catid'=>$catid, 'vpath'=>$virtualpath));
- $complete = true;
- }
-
- //URL生成
- //ここでは$baseurlの決定と、$set(=extra)の用意だけをする。最終的な組み立てはaddLinkParams()に委ねる。
- //ノーマルURLでも動くと思われるが、きちんと検証してない。
- function event_GenerateURL(&$data)
- {
- // if another plugin already generated the URL
- if ($data['completed']) return;
-
- global $manager, $CONF, $blog, $blogid;
- static $defBlogURL, $oldItemID, $oldBlogID, $oldBaseurl;
-
- //フィード配信時の例外。必ずDB側のburlを取得する。
- $flg_feed = (strpos($CONF['Self'], 'xml') === 0 or strpos($CONF['Self'], 'atom') === 0);
-
- if ($defBlogURL == null) {
- $defBlogURL = getBlogURLFromID($CONF['DefaultBlog']);
- }
-
- $params =& $data['params'];
- $set =& $params['extra']; //addLinkParams()に送る追加パラメータ
-
- //追加パラメータの例外処理
- if ($this->flg_fancy and $set['archivelist']) {
- $set['archivelist'] = '[[NONE]]'; //キーのみ、値無し(dummy)
- }
-
- //blogidはこの時点で必ず決まっているのでそれと$params['hogeid']から割り出したblogidとを比較
- //呼び出しブログのときはCONF['Self'](絶対URL指定)、それ以外のときは必ずburlを参照してベースurlとする
- switch ($data['type']) {
- case 'item':
- if ($params['itemid'] == $oldItemID) {
- $params['blogid'] = $oldBlogID;
- $baseurl = $oldBaseurl;
- }
- else {
- $params['blogid'] = $this->_getBlogIDFromItemID($params['itemid']);
- $baseurl = ($blogid == $params['blogid'] and !$flg_feed) ? $CONF['ItemURL'] : getBlogURLFromID($params['blogid']);
- $oldItemID = $params['itemid'];
- $oldBlogID = $params['blogid'];
- $oldBaseurl = $baseurl;
- }
-
- $set['blogid'] = $params['blogid'];
- $set['itemid'] = $params['itemid'];
- if ($CONF['NP_SimpleURL']['ShowCategoryAlways']) {
- $set['catid'] = ($params['catid']) ? $params['catid'] : $this->_getCatIDFromItemID($params['itemid']);
- }
- break;
-
- case 'member':
- $params['blogid'] = $blogid;
- $baseurl = $CONF['MemberURL'];
-
- $set['blogid'] = $params['blogid'];
- $set['memberid'] = $params['memberid'];
- if (isset($set['catid'])) unset($set['catid']); //例外
- break;
-
- case 'category':
- $params['blogid'] = $this->_getBlogIDFromCatID($params['catid']);
- $baseurl = ($blogid == $params['blogid'] and !$flg_feed) ? $CONF['CategoryURL'] : getBlogURLFromID($params['blogid']);
-
- $set['blogid'] = $params['blogid'];
- $set['catid'] = $params['catid'];
- break;
-
- case 'archivelist':
- if (!$params['blogid']) $params['blogid'] = $CONF['DefaultBlog'];
- $baseurl = ($blogid == $params['blogid'] and !$flg_feed) ? $CONF['ArchiveListURL'] : getBlogURLFromID($params['blogid']);
-
- $set['blogid'] = $params['blogid'];
- if ($this->flg_fancy) {
- $set['archivelist'] = '[[NONE]]'; //キーのみ、値無し(dummy)
- }
- else {
- $set['archivelist'] = $params['blogid'];
- }
- break;
-
- case 'archive':
- $baseurl = ($blogid == $params['blogid'] and !$flg_feed) ? $CONF['ArchiveURL'] : getBlogURLFromID($params['blogid']);
-
- $set['blogid'] = $params['blogid'];
- $set['archive'] = $params['archive'];
- break;
-
- case 'blog':
- $baseurl = ($blogid == $params['blogid'] and !$flg_feed) ? $CONF['BlogURL'] : getBlogURLFromID($params['blogid']);
-
- $set['blogid'] = $params['blogid'];
- break;
- }
-
- //addLinkParams()の変更はコアファイルを書き換えるか、NP_SimpleURL::addLinkParams()を呼ぶかのいずれか
- $data['url'] = $this->addLinkParams($baseurl, $set, '.html', true);
- $data['completed'] = true;
- }
-
- /**
- * add link params
- *
- * 単独でglobalfunctions.phpの addLinkParams() にコピペ・上書きしても動くはず。
- *
- * @static
- * @access public
- * @param $link base link
- * @param $params parameters (assoc array)
- * @param $postfix postfix to add extension like ".html"
- * @param $flg_check flag for event_GenerateURL
- */
- function addLinkParams($link, $params, $postfix='', $flg_check=false)
- {
- global $manager, $CONF, $blog, $blogid;
- static $defBlogURL, $orderbase;
-
- if (! is_array($params) ) return $link;
-
- $blogid_copy = $params['blogid']; //後の処理で消える場合があるのでコピーをとっておく
-
- if ($flg_check) { //GenerateURLからの処理の続き
- if (!$CONF['NP_SimpleURL']['ShowBlogAlways']) {
- if ($defBlogURL == null) $defBlogURL = getBlogURLFromID($CONF['DefaultBlog']);
-
- if ($params['archivelist']) { //archivelistの例外
- unset($params['blogid']);
- }
- else if ($CONF['URLMode'] == 'pathinfo' and
- ($params['blogid'] == $CONF['DefaultBlog'] or //既定のブログ→blogid不要
- $link != $defBlogURL) //既定以外の呼び出しURLはselectBlog()前提→blogid不要
- ) {
- unset($params['blogid']);
- }
- }
- }
-
- if ($CONF['URLMode'] == 'pathinfo') {
- //パラメータの並び順を取得する
- $order = array();
- if (!$orderbase) {
- $orderbase = $CONF['NP_SimpleURL']['URLOrder'];
- asort($orderbase); //優先順位でソート
- }
- foreach (array_keys($orderbase) as $key) $order[$key] = ''; //先にキーをセット
-
- //$paramsに対応するキーのマッピング
- //ここに割り込む必要がないように、外部からのURL拡張は キーを書き換えずに使える名前にすること。
- $keymap = array(
- 'blogid' => $CONF['BlogKey'],
- 'catid' => $CONF['CategoryKey'],
- 'special' => $CONF['SpecialskinKey'],
- 'itemid' => $CONF['ItemKey'],
- 'archivelist' => $CONF['ArchivesKey'],
- 'archive' => $CONF['ArchiveKey'],
- 'memberid' => $CONF['MemberKey'],
- );
-
- //キーや値の書き換え、並び順への追加
- foreach ($params as $key => $value) {
- //blogid, catid, memberid, itemidの書き換え(数値→文字列へ)
- if ($CONF['NP_SimpleURL']['UseAlias']) {
- switch ($key) {
- case 'blogid':
- $value = getBlogAliasFromID($value);
- break;
- case 'catid':
- $value = getCatAliasFromID($value, $blogid_copy);
- break;
- case 'itemid':
- $value = getItemAliasFromID($value);
- break;
- case 'memberid':
- $value = getMemberAliasFromID($value);
- break;
- }
- }
-
- if ($keymap[$key]) $key = $keymap[$key]; //該当キーを$CONF['hogeKey']に書き換え
- $order[$key] = $value; //並び順指定があればそのキーに値を格納。なければ$orderの最後尾に新規追加されていく
- }
-
- //実際にURLを組み立てる
- foreach ($order as $key => $value) {
- if ($value == '') continue;
-
- if ($CONF['NP_SimpleURL']['DropKeys'] and ($key == $CONF['BlogKey'] or $key == $CONF['CategoryKey'])) {
- $link .= ((substr($link, -1) == '/') ? '' : '/') . $value . '/'; //ディレクトリ構造を模して最後を閉じる
- }
- else if ($CONF['NP_SimpleURL']['DropKeys'] and $key == $CONF['ItemKey']) {
- $link .= ((substr($link, -1) == '/') ? '' : '/') . rawurlencode($value);
- }
- else if ($value == '[[NONE]]') { //キーのみ、値無し
- $link .= ((substr($link, -1) == '/') ? '' : '/') . $key;
- }
- else {
- $link .= ((substr($link, -1) == '/') ? '' : '/') . $key . '/' . rawurlencode($value);
- }
- }
-
- $link .= (substr($link, -1) == '/') ? '' : $postfix;
- }
- else { //normal url
- foreach ($params as $param => $value) {
- $link .= ((strpos($link, '?') === false) ? '?' : '&') . $param . '=' . urlencode($value);
- }
- }
- return $link;
- }
-
- /**
- * setter of url order
- *
- * @static
- * @access public
- * @param $key key of the parameter
- * @param $rank rank for order (integer; the smaller number is the higher rank)
- */
- function setURLOrder($key, $rank)
- {
- global $CONF;
- $CONF['NP_SimpleURL']['URLOrder'][$key] = $rank;
- }
-
-
-
- /* ----------------- helper methods ----------------- */
-
- function _quoteSmart($val)
- {
- if (get_magic_quotes_gpc()) $val = stripslashes($val);
- if (preg_match('/^[0-9]+$/', $val)) {
- $qmark = '';
- }
- else {
- $qmark = '"';
- $val = mysql_real_escape_string($val);
- }
- return $qmark . $val . $qmark;
- }
-
- function _getBlogIDFromAlias($name)
- {
- static $buff;
-
- if (! isset($buff)) {
- $buff[$name] = quickQuery('SELECT bnumber as result FROM ' . sql_table('blog') .
- ' WHERE bshortname="' . mysql_real_escape_string($name) . '"');
- }
- return ($buff[$name]) ? $buff[$name] : 0;
- }
-
- function _getMemberIDFromAlias($name)
- {
- static $buff;
-
- $name = str_replace('_', ' ', $name);
- if (!$buff[$name]) {
- $buff[$name] = quickQuery('SELECT mnumber as result FROM ' . sql_table('member') .
- ' WHERE mname="' . mysql_real_escape_string($name) .'"');
- }
- return ($buff[$name]) ? $buff[$name] : 0;
- }
-
- function _getCatIDFromAlias($name)
- {
- global $blogid;
- static $buff;
-
- if (! isset($buff)) {
- //$buff = array_flip($this->getAllCategoryOptions('cshortname'));
- $query = 'SELECT catid, cshortname FROM ' . sql_table('plug_simpleurl');
- if ($blogid) $query .=' WHERE blogid='. (int)$blogid;
- $res = sql_query($query);
-
- while($data = mysql_fetch_assoc($res)) {
- $buff[ $data['cshortname'] ] = $data['catid'];
- }
- }
-
- return ($buff[$name]) ? $buff[$name] : 0;
- }
-
- function _getItemIDFromAlias($name)
- {
- /*static $buff;
-
- $name = urldecode($name);
- if (!$buff[$name]) {
- $buff[$name] = quickQuery('SELECT inumber as result FROM ' . sql_table('item') .
- ' WHERE ititle="' . mysql_real_escape_string($name) . '"');
- }
- return ($buff[$name]) ? $buff[$name] : 0;
- */
- if (preg_match('/-([0-9]+?)$/', $name, $m)) {
- return (int)$m[1];
- }
- else {
- return 0;
- }
- }
-
- function _getDataFromItemID($itemid, $type='')
- {
- $itemid = (int)$itemid;
-
- if (!$this->arr_item[$itemid]) {
- $res = sql_query('SELECT iblog, icat, ititle FROM ' . sql_table('item') . ' WHERE inumber=' . $itemid);
- if (mysql_num_rows($res)) {
- $this->arr_item[$itemid] = mysql_fetch_assoc($res);
- }
- }
- if ($type) return $this->arr_item[$itemid][$type];
- else return $this->arr_item[$itemid];
- }
-
- function _getBlogIDFromItemID($itemid)
- {
- return $this->_getDataFromItemID($itemid, 'iblog');
- }
-
- function _getCatIDFromItemID($itemid)
- {
- return $this->_getDataFromItemID($itemid, 'icat');
- }
-
- function _getBlogIDFromCatID($catid)
- {
- static $buff;
-
- $catid = (int)$catid;
- if (! $buff[$catid]) {
- $res = sql_query('SELECT catid, cblog FROM ' . sql_table('category'));
- if (mysql_num_rows($res)) {
- while ($data = mysql_fetch_assoc($res)) {
- $buff[ $data['catid'] ] = $data['cblog'];
- }
- }
- }
- return $buff[$catid];
- }
-
- function _getCatNameFromID($id)
- {
- return quickQuery('SELECT cname as result FROM '. sql_table('category') .' WHERE catid='. (int)$id);
- }
-
- function _canEdit($type='admin')
- {
- global $member;
-
- $query = 'SELECT * FROM '.sql_table('team').' WHERE tmember='. $member->getID();
- if ($type == 'admin') $query .= ' and tadmin=1';
- return (mysql_num_rows(sql_query($query)) != 0);
- }
-
-
- /* ----------------- methods for admin area ----------------- */
-
- function _makeAdminArea(&$oPluginAdmin)
- {
- global $manager, $member;
-
- $adminurl = $this->getAdminURL();
-
- if (!$member->isLoggedIn() or !$this->_canEdit()) {
- $oPluginAdmin->start();
- echo '<p>' . _ERROR_DISALLOWED . '</p>';
- $oPluginAdmin->end();
- exit;
- }
-
-//<script type='text/javascript' src='../../javascript/numbercheck.js'></script>
- $oPluginAdmin->start("
-<script type='text/javascript'>
-<!--
-
-function confirm_check(message) {
- if( confirm(message) ){
- sent = true;
- return true;
- }
- else {
- return false;
- }
-}
-
-// -->
-</script>
-<style type='text/css'>
-<!--
-p.message {
- font-weight: bold;
- color: #c00;
-}
-form.button {
- display: inline;
-}
-table.group {
- margin: 5px 0;
-}
-table.group td {
- background-color: #ddd;
-}
-table.link {
- margin: 0;
-}
-table.link th {
- /*background-color: #ddd;*/
-}
-table.link td.stripe {
- background-color: #eee;
-}
-span.idlabel {
- border: 1px solid #666;
- padding: 1px 2px;
- background-color: #999;
- color: white;
-}
--->
-</style>
-");
-
- echo "<h2>SimpleURL</h2>";
-
- $action = requestVar('action');
- $actions = array (
- 'index',
- 'update',
- );
-
- if ($action == '') {
- $this->_makeCatAliasForm();
- }
- else if (in_array($action, $actions)) {
- if (!$manager->checkTicket()) {
- echo '<p class="error">Error: ' . _ERROR_BADTICKET . '</p>';
- }
- else {
- switch ($action) {
- case 'index':
- $this->_makeCatAliasForm();
- break;
- case 'update':
- $isok = $this->_updateCatAlias();
- if ($isok) echo '<p class="message">Updated successfully.</p>';
- else echo '<p class="error">Error: Update failed (in some records).</p>';
-
- $this->_makeCatAliasForm();
- break;
- }
- }
- }
- else {
- echo '<p class="error">Error: Invalid action type.</p>';
- }
- $oPluginAdmin->end();
- }
-
- function _makeCatAliasForm()
- {
- global $manager;
-
- $adminurl = $this->getAdminURL();
- $action = 'update';
-
- echo <<<OUT
-<h3>Setting: Category Alias</h3>
-<table>
-<form method="post" action="{$adminurl}">
-<input type="hidden" name="action" value="{$action}" />
-<input type="hidden" name="type" value="categoryalias" />
-OUT;
- $manager->addTicketHidden();
- echo <<<OUT
-<tr>
- <th>Blog</th><th>Category</th><th>Alias Name [0-9a-z_-]</th>
-</tr>
-OUT;
- $data = getCatAliasesFromDB();
- foreach ($data as $blogid => $bdata) {
- $blogname = htmlspecialchars(getBlogNameFromID($blogid));
- foreach ($bdata as $catid => $cshortname) {
- $catname = htmlspecialchars($this->_getCatNameFromID($catid));
- echo <<<OUT
-<tr>
- <td><span class="idlabel">ID:{$blogid}</span> {$blogname}</td><td><span class="idlabel">ID:{$catid}</span> {$catname}</td><td><input type="text" name="catids[{$catid}]" value="{$cshortname}" size="20" /></td>
-</tr>
-OUT;
- }
- }
- echo <<<OUT
-<tr>
- <th colspan="3" style="text-align:center"><input type="submit" value="Submit"></th>
-</tr>
-</form>
-</table>
-
-OUT;
- }
-
- function _updateCatAlias()
- {
- if (!is_array($_POST['catids'])) return false;
-
- $err = 0;
- foreach ($_POST['catids'] as $catid => $cshortname) {
- $cshortname = strtolower($cshortname);
- $cshortname = preg_replace('/[^0-9a-z_-]/', '', $cshortname);
- if ($cshortname == '') {
- $err++;
- continue;
- }
- $query = sprintf("UPDATE %s SET cshortname=%s WHERE catid=%d",
- sql_table("plug_simpleurl"),
- $this->_quoteSmart($cshortname),
- $this->_quoteSmart($catid)
- );
- $res = sql_query($query);
- if (!$res) $err++;
- }
- return ($err == 0);
- }
-
-}
-?>
+<?php\r
+/*\r
+ NP_SimpleURL : Improve url handling with a simple format.\r
+ \r
+ License\r
+ -------\r
+ This program is free software; you can redistribute it and/or\r
+ modify it under the terms of the GNU General Public License\r
+ as published by the Free Software Foundation; either version 2\r
+ of the License, or (at your option) any later version.\r
+ (see nucleus/documentation/index.html#license for more info)\r
+ \r
+ Usage\r
+ -----\r
+ Install this plugin and turn "FancyURLs mode" on.\r
+ \r
+ In index.php :\r
+ Set absolute url (http://...) to $CONF['Self'].\r
+ Set blog's shortname to $CONF['NP_SimpleURL']['selectBlog'] before including config.php. (optional) \r
+ Set selectBlog('shortname') before selector(). (optional)\r
+ \r
+ In fancyurls.config.php or index.php :\r
+ You can use some features (flags).\r
+ \r
+ $CONF['NP_SimpleURL']['UseAlias'] = 1; //convert id number to alias (shortname). don't turn "DropKeys" on if "UseAlias" is off.\r
+ $CONF['NP_SimpleURL']['DropKeys'] = 1; //drop keys for blog, category and item\r
+ $CONF['NP_SimpleURL']['ShowBlogAlways'] = 0; //show blog always\r
+ $CONF['NP_SimpleURL']['ShowCategoryAlways'] = 1; //show category always (in permalink)\r
+ \r
+ 誤動作にハマらないために注意すべき事柄:\r
+ 1.実在するディレクトリ名と同じ名前を、URL修飾キーやエイリアスに使わない。\r
+ 2.スキンタイプ、URL修飾キーなどで予約済みの名前をエイリアスに使わない。\r
+ 3.ブログ間で同名のカテゴリーエイリアスを使う場合は index.phpに $CONF['NP_SimpleURL']['selectBlog']をセットする。\r
+ ※2の制約から解放されたい場合は DropKeys を無効にすること。\r
+ ※3の制約は ShowBlogAlways を有効にしてURLにブログ情報を必ず含めることでも解消できる。\r
+ \r
+ History\r
+ -------\r
+ 2008-12-15 v0.3 : Add old url redirection. Add item var.\r
+ : Change item page's url format. (yu)\r
+ 2008-07-12 v0.21: Improve function for category alias. (yu)\r
+ 2008-06-08 v0.2 : Add some new features. Support alias names. (yu)\r
+ 2008-05-02 v0.1 : First release. (yu http://nucleus.datoka.jp/)\r
+*/\r
+\r
+\r
+/* ----------------- additional global functions ----------------- */\r
+\r
+/* addLinkParams()をグローバル関数として切り出せるように下記も一応グローバルで宣言しておく */\r
+\r
+if(!function_exists('getBlogURLFromID')) {\r
+ function getBlogURLFromID($blogid)\r
+ {\r
+ static $buff;\r
+ \r
+ $blogid = (int)$blogid;\r
+ if (!$buff[$blogid]) {\r
+ $res = sql_query('SELECT bnumber, burl FROM ' . sql_table('blog'));\r
+ if (mysql_num_rows($res)) {\r
+ while ($data = mysql_fetch_assoc($res)) {\r
+ $buff[ $data['bnumber'] ] = $data['burl'];\r
+ }\r
+ }\r
+ }\r
+ return $buff[$blogid];\r
+ }\r
+}\r
+\r
+if(!function_exists('getBlogAliasFromID')) {\r
+ function getBlogAliasFromID($id)\r
+ {\r
+ static $buff;\r
+ \r
+ $id = (int)$id;\r
+ if (!$buff[$id]) {\r
+ $buff[$id] = quickQuery('SELECT bshortname as result FROM ' . sql_table('blog') . ' WHERE bnumber=' . $id);\r
+ }\r
+ return ($buff[$id]) ? $buff[$id] : $id;\r
+ }\r
+}\r
+\r
+if(!function_exists('getMemberAliasFromID')) {\r
+ function getMemberAliasFromID($id)\r
+ {\r
+ static $buff;\r
+ \r
+ $id = (int)$id;\r
+ if (!$buff[$id]) {\r
+ $buff[$id] = quickQuery('SELECT mname as result FROM ' . sql_table('member') . ' WHERE mnumber=' . $id);\r
+ $buff[$id] = str_replace(' ', '_', $buff[$id]);\r
+ }\r
+ return ($buff[$id]) ? $buff[$id] : $id;\r
+ }\r
+}\r
+\r
+if(!function_exists('getCatAliasFromID')) {\r
+ function getCatAliasFromID($id, $blogid)\r
+ {\r
+ global $manager;\r
+ static $buff;\r
+ \r
+ $id = (int)$id;\r
+ if (! isset($buff)) {\r
+ $buff = getCatAliasesFromDB();\r
+ }\r
+ return ($buff[$blogid][$id]) ? $buff[$blogid][$id] : $id;\r
+ }\r
+}\r
+\r
+if(!function_exists('getCatAliasesFromDB')) {\r
+ function getCatAliasesFromDB()\r
+ {\r
+ $arr = array();\r
+ $res = sql_query('SELECT catid, blogid, cshortname FROM ' . sql_table('plug_simpleurl') .' ORDER BY catid');\r
+ while($data = mysql_fetch_assoc($res)) {\r
+ $arr[ $data['blogid'] ][$data['catid']] = $data['cshortname'];\r
+ }\r
+ return $arr;\r
+ }\r
+}\r
+\r
+if(!function_exists('getItemAliasFromID')) {\r
+ function getItemAliasFromID($id)\r
+ {\r
+ global $manager;\r
+ \r
+ //return (int)$id; //use itemid only\r
+ \r
+ if ($manager->pluginInstalled('NP_SimpleURL')) { //use title\r
+ $obj =& $manager->getPlugin('NP_SimpleURL');\r
+ $t = strip_tags($obj->_getDataFromItemID($id, $type='ititle'));\r
+ if (preg_match('/[^\x00-\x7F]/', $t)) { \r
+ //半角文字以外が入っている場合はアイテムIDのみ\r
+ $t = (int)$id;\r
+ }\r
+ else {\r
+ //半角文字の場合はURLで安全に使用可能な文字以外を'_'で置換\r
+ $t = mb_substr(preg_replace('/[^a-zA-Z0-9_.!~*()-]/', '_', $t), 0, 40) .'-'. (int)$id;\r
+ }\r
+ return $t;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+class NP_SimpleURL extends NucleusPlugin\r
+{\r
+ function getName() { return 'Simple URL'; }\r
+ function getAuthor() { return 'yu'; }\r
+ function getURL() { return 'http://nucleus.datoka.jp/'; }\r
+ function getVersion() { return '0.3'; }\r
+ function getMinNucleusVersion() { return 322; }\r
+ function supportsFeature($what) { return (int)($what == 'SqlTablePrefix'); }\r
+ function hasAdminArea() { return 1; }\r
+ function getDescription()\r
+ {\r
+ return 'Improve url handling with a simple format.';\r
+ }\r
+ function getEventList()\r
+ {\r
+ return array(\r
+ 'PostAuthentication',\r
+ 'ParseURL', \r
+ 'GenerateURL', \r
+ 'PostAddCategory', \r
+ 'PostDeleteCategory', \r
+ 'PostMoveCategory', \r
+ 'QuickMenu'\r
+ );\r
+ }\r
+ \r
+ var $flg_fancy;\r
+ var $arr_item;\r
+ \r
+ function install()\r
+ {\r
+ $this->createOption('flg_qmenu', 'Show on quick menu', 'yesno', 'yes');\r
+ $this->createOption('flg_erase', 'Erase data on uninstallation', 'yesno', 'no');\r
+ \r
+ //テーブルが存在するかチェックする\r
+ $chktable = sql_query("SHOW TABLES LIKE '". sql_table('plug_simpleurl') ."'");\r
+ if (mysql_num_rows($chktable)) return;\r
+ \r
+ //存在しなければテーブル生成&データ代入\r
+ sql_query("CREATE TABLE IF NOT EXISTS ". sql_table('plug_simpleurl') ." (\r
+ catid INT UNSIGNED NOT NULL DEFAULT 0 PRIMARY KEY,\r
+ blogid INT UNSIGNED NOT NULL DEFAULT 0,\r
+ cshortname VARCHAR(50) NOT NULL DEFAULT '')");\r
+ $res = sql_query("SELECT catid, cblog FROM ". sql_table('category'));\r
+ while ($data = mysql_fetch_assoc($res)) {\r
+ sql_query("INSERT ". sql_table('plug_simpleurl') \r
+ ." SET catid=". $data['catid'] .", blogid=". $data['cblog'] .", cshortname='c". $data['catid'] ."'");\r
+ }\r
+ }\r
+ \r
+ function uninstall()\r
+ {\r
+ if ($this->getOption('flg_erase') == 'yes') {\r
+ sql_query("DROP TABLE ". sql_table('plug_simpleurl'));\r
+ }\r
+ }\r
+ \r
+ function init()\r
+ {\r
+ global $CONF;\r
+ \r
+ $this->flg_fancy = ($CONF['URLMode'] == 'pathinfo');\r
+ \r
+ if ($this->flg_fancy) {\r
+ //URLパラメータの並び順(あらかじめキーを作っておく)\r
+ //外部プラグインは各々init()で$CONF['HogeKey']登録と、NP_SimpleURL::setURLOrder('hoge',N)する。\r
+ $CONF['NP_SimpleURL']['URLOrder'] = array(\r
+ $CONF['BlogKey'] => 0, //1番目\r
+ $CONF['CategoryKey'] => 1, //2番目\r
+ $CONF['SpecialskinKey'] => 2, //3番目\r
+ $CONF['ArchiveKey'] => 10, //以下同順\r
+ $CONF['ArchivesKey'] => 10, \r
+ $CONF['ItemKey'] => 10, \r
+ $CONF['MemberKey'] => 10, \r
+ );\r
+ }\r
+ }\r
+ \r
+ /* ----------------- event methods ----------------- */\r
+ \r
+ function event_PostAuthentication(&$data)\r
+ {\r
+ //wake up! (nothing to do)\r
+ //外部からNP_SimpleURLのメソッドを静的呼び出しするときの便宜を考えて。\r
+ //NP_SimpleURL::addLinkParams()など\r
+ }\r
+ \r
+ function event_QuickMenu(&$data)\r
+ {\r
+ global $member;\r
+ \r
+ if ($this->getOption('flg_qmenu') != 'yes') return;\r
+ if (!$this->_canEdit()) return;\r
+ \r
+ array_push(\r
+ $data['options'], \r
+ array(\r
+ 'title' => 'Simple URL',\r
+ 'url' => $this->getAdminURL(),\r
+ 'tooltip' => 'Setting of category alias'\r
+ )\r
+ );\r
+ }\r
+ \r
+ function event_PostMoveCategory(&$data)\r
+ {\r
+ sql_query("UPDATE ". sql_table('plug_simpleurl') \r
+ ." SET blogid=". $data['destblog']->getID() ." WHERE catid=". $data['catid']);\r
+ }\r
+ \r
+ function event_PostAddCategory(&$data)\r
+ {\r
+ sql_query("INSERT ". sql_table('plug_simpleurl') \r
+ ." SET catid=". $data['catid'] .", blogid=". $data['blog']->getID() .", cshortname='c". $data['catid'] ."'");\r
+ }\r
+ \r
+ function event_PostDeleteCategory($data)\r
+ {\r
+ sql_query("DELETE ". sql_table('plug_simpleurl') ." WHERE catid=". $data['catid']);\r
+ }\r
+ \r
+ //URLパース\r
+ function event_ParseURL(&$pdata)\r
+ {\r
+ \r
+ \r
+ // nothing to do if another plugin already parsed the URL\r
+ if ($pdata['complete']) return;\r
+ \r
+ global $CONF, $blogid, $catid, $itemid, $memberid, $archive, $archivelist;\r
+ \r
+ // in admin area\r
+ if ($CONF['UsingAdminArea']) return;\r
+ \r
+ $complete =& $pdata['complete'];\r
+ $virtualpath =& $pdata['info'];\r
+ $virtualpath = preg_replace('/\.html$/', '', $virtualpath);\r
+ \r
+ //selectBlog()の先取り。URLパースのタイミング上、selectBlog()では遅いため。\r
+ if (!$blogid and $CONF['SimpleURL']['selectBlog']) {\r
+ selectBlog( $CONF['SimpleURL']['selectBlog'] );\r
+ }\r
+ \r
+ //リダイレクト処理(NormalURLからFancyURLへ)\r
+ if ($virtualpath == '') {\r
+ $extra = '';\r
+ $newurl = '';\r
+ if ($itemid) {\r
+ if ($blogid) $extra['blogid'] = $blogid;\r
+ if ($catid) $extra['catid'] = $catid;\r
+ $newurl = createItemLink($itemid, $extra);\r
+ }\r
+ else if ($memberid) {\r
+ if ($blogid) $extra['blogid'] = $blogid;\r
+ $newurl = createMemberLink($memberid, $extra);\r
+ }\r
+ else if ($archivelist) {\r
+ if ($catid) $extra['catid'] = $catid;\r
+ $newurl = createArchiveListLink($archivelist, $extra);\r
+ }\r
+ else if ($archive) {\r
+ if ($catid) $extra['catid'] = $catid;\r
+ $newurl = createArchiveLink($blogid, $archive, $extra);\r
+ }\r
+ else if ($catid) {\r
+ if ($blogid) $extra['blogid'] = $blogid;\r
+ $newurl = createCategoryLink($catid, $extra);\r
+ }\r
+ /*else if ($blogid) {\r
+ $newurl = createBlogidLink($blogid, $extra);\r
+ $this->_redirect301($newurl);\r
+ }*/\r
+ if ($newurl != '') {\r
+ if ($this->_isValidURL($newurl)) $this->_http301($newurl);\r
+ else $this->_http404();\r
+ }\r
+ }\r
+ \r
+ //パース処理開始\r
+ $data = explode("/", $virtualpath );\r
+ for ($i = 0; $i < sizeof($data); $i++) {\r
+ switch ($data[$i]) {\r
+ case $CONF['ItemKey']: // item/1 (itemid) or item/name (urlencoded ititle)\r
+ $i++;\r
+ if ($i < sizeof($data) ) {\r
+ if (is_numeric($data[$i])) $itemid = intval($data[$i]);\r
+ else $itemid = $this->_getItemIDFromAlias($data[$i]);\r
+ }\r
+ break;\r
+\r
+ case $CONF['ArchivesKey']: // archives\r
+ if ($blogid) {\r
+ $archivelist = $blogid;\r
+ }\r
+ else {\r
+ $archivelist = $CONF['DefaultBlog'];\r
+ }\r
+ break;\r
+\r
+ case $CONF['ArchiveKey']: // archive/yyyy-mm\r
+ $i++;\r
+ if ($i < sizeof($data) ) {\r
+ $archive = $data[$i];\r
+ }\r
+ break;\r
+\r
+ case $CONF['BlogKey']: // blog/1 or blog/bshortname\r
+ case 'blogid':\r
+ $i++;\r
+ if ($i < sizeof($data) ) {\r
+ if (is_numeric($data[$i])) $blogid = intval($data[$i]);\r
+ else $blogid = $this->_getBlogIDFromAlias($data[$i]);\r
+ }\r
+ break;\r
+\r
+ case $CONF['CategoryKey']: // category/1 (catid) or category/aliasname\r
+ case 'catid':\r
+ $i++;\r
+ if ($i < sizeof($data) ) {\r
+ if (is_numeric($data[$i])) $catid = intval($data[$i]);\r
+ else $catid = $this->_getCatIDFromAlias($data[$i]);\r
+ }\r
+ break;\r
+\r
+ case $CONF['MemberKey']: // member/1 (memberid) or member/mname\r
+ $i++;\r
+ if ($i < sizeof($data) ) {\r
+ if (is_numeric($data[$i])) $memberid = intval($data[$i]);\r
+ else $memberid = $this->_getMemberIDFromAlias($data[$i]);\r
+ }\r
+ break;\r
+\r
+ case $CONF['SpecialskinKey']: //extra/specialname\r
+ $i++;\r
+ if ($i < sizeof($data) ) {\r
+ $_REQUEST['special'] = $data[$i];\r
+ }\r
+ break;\r
+\r
+ default:\r
+ //無効なキーは捨てる\r
+ if ($data[$i] == '') break; //skip\r
+ \r
+ $flg_num = (is_numeric($data[$i]));\r
+ \r
+ //拡張キーと合致するかスキャンする\r
+ $exkey = ucfirst($data[$i]) . 'Key';\r
+ if (isset($CONF[$exkey])) {\r
+ $exstore =& $_REQUEST; //代入先はリクエスト変数\r
+ \r
+ if (!$exstore[ $CONF[$exkey] ]) { //対象が未定義なら代入を許可する\r
+ $i++;\r
+ $exstore[ $CONF[$exkey] ] = $data[$i]; //そのまま代入してるので、利用時は値のチェックを忘れずに。\r
+ }\r
+ break;\r
+ }\r
+ \r
+ //debuglog('check non-key val: '.$data[$i]);\r
+ //「キー無し」の可能性をチェック。ここでは数値のみの値を避ける\r
+ $tempid = 0;\r
+ if ($CONF['NP_SimpleURL']['DropKeys'] and !$flg_num and preg_match('/^[0-9a-z_-]+$/', $data[$i])) {\r
+ if (!$blog_done and $i == 0 and $CONF['NP_SimpleURL']['ShowBlogAlways']) { //ブログのキー無しは ShowBlogAlways が有効なときのみ\r
+ $tempid = $this->_getBlogIDFromAlias($data[$i]);\r
+ if ($tempid) {\r
+ //debuglog('hit: blog'.$tempid. ' ' .$data[$i]);\r
+ $blogid = $tempid;\r
+ $blog_done = true;\r
+ break;\r
+ }\r
+ //debuglog('through: blog '.$i);\r
+ }\r
+ if (!$cat_done and $i < 2) { //カテゴリーのキー無しの可能性をチェック\r
+ $tempid = $this->_getCatIDFromAlias($data[$i]);\r
+ if ($tempid) {\r
+ //debuglog('hit: cat'.$tempid. ' ' .$data[$i]);\r
+ $catid = $tempid;\r
+ $cat_done = true;\r
+ break;\r
+ }\r
+ //debuglog('through: cat '.$i);\r
+ }\r
+ }\r
+ //アイテムのキー無しの可能性をチェック。数値のみも受け付ける(キー無し数値はアイテムとみなされる)\r
+ if ($CONF['NP_SimpleURL']['DropKeys'] and !$item_done and\r
+ (\r
+ ($i >= 0 and !$CONF['NP_SimpleURL']['ShowBlogAlways']) or \r
+ ($i >= 1 and $CONF['NP_SimpleURL']['ShowBlogAlways'] ^ $CONF['NP_SimpleURL']['ShowCategoryAlways']) or \r
+ ($i >= 2 and $CONF['NP_SimpleURL']['ShowBlogAlways'] & $CONF['NP_SimpleURL']['ShowCategoryAlways']) \r
+ )\r
+ ) {\r
+ if ($flg_num) $tempid = (int)$data[$i];\r
+ else $tempid = $this->_getItemIDFromAlias($data[$i]);\r
+ \r
+ if ($tempid) {\r
+ //debuglog('hit: item'.$tempid. ' ' .$data[$i]);\r
+ $itemid = $tempid;\r
+ $item_done = true;\r
+ break;\r
+ }\r
+ //debuglog('through: item '.$i);\r
+ }\r
+ //debuglog('through: last '.$i);\r
+ //意味のないURLとみなし、404にする\r
+ $this->_http404();\r
+ }\r
+ }\r
+ //debuglog(array('blogid'=>$blogid, 'catid'=>$catid, 'vpath'=>$virtualpath));\r
+ $complete = true;\r
+ }\r
+ \r
+ //URL生成\r
+ //ここでは$baseurlの決定と、$set(=extra)の用意だけをする。最終的な組み立てはaddLinkParams()に委ねる。\r
+ //ノーマルURLでも動くと思われるが、きちんと検証してない。\r
+ function event_GenerateURL(&$data)\r
+ {\r
+ // if another plugin already generated the URL\r
+ if ($data['completed']) return;\r
+ \r
+ global $manager, $CONF, $blog, $blogid;\r
+ static $defBlogURL, $oldItemID, $oldBlogID, $oldBaseurl;\r
+ \r
+ //フィード配信時の例外。必ずDB側のburlを取得する。\r
+ $flg_feed = (strpos($CONF['Self'], 'xml') === 0 or strpos($CONF['Self'], 'atom') === 0);\r
+ \r
+ if ($defBlogURL == null) {\r
+ $defBlogURL = getBlogURLFromID($CONF['DefaultBlog']);\r
+ }\r
+ \r
+ $params =& $data['params'];\r
+ $set =& $params['extra']; //addLinkParams()に送る追加パラメータ\r
+ \r
+ //追加パラメータの例外処理\r
+ if ($this->flg_fancy and $set['archivelist']) {\r
+ $set['archivelist'] = '[[NONE]]'; //キーのみ、値無し(dummy)\r
+ }\r
+ \r
+ //blogidはこの時点で必ず決まっているのでそれと$params['hogeid']から割り出したblogidとを比較\r
+ //呼び出しブログのときはCONF['Self'](絶対URL指定)、それ以外のときは必ずburlを参照してベースurlとする\r
+ switch ($data['type']) {\r
+ case 'item':\r
+ if ($params['itemid'] == $oldItemID) {\r
+ $params['blogid'] = $oldBlogID;\r
+ $baseurl = $oldBaseurl;\r
+ }\r
+ else {\r
+ $params['blogid'] = $this->_getBlogIDFromItemID($params['itemid']);\r
+ $baseurl = ($blogid == $params['blogid'] and !$flg_feed) ? $CONF['ItemURL'] : getBlogURLFromID($params['blogid']);\r
+ $oldItemID = $params['itemid'];\r
+ $oldBlogID = $params['blogid'];\r
+ $oldBaseurl = $baseurl;\r
+ }\r
+ \r
+ $set['blogid'] = $params['blogid'];\r
+ $set['itemid'] = $params['itemid'];\r
+ if ($CONF['NP_SimpleURL']['ShowCategoryAlways']) {\r
+ $set['catid'] = ($params['catid']) ? $params['catid'] : $this->_getCatIDFromItemID($params['itemid']);\r
+ }\r
+ break;\r
+ \r
+ case 'member':\r
+ $params['blogid'] = $blogid;\r
+ $baseurl = $CONF['MemberURL'];\r
+ \r
+ $set['blogid'] = $params['blogid'];\r
+ $set['memberid'] = $params['memberid'];\r
+ if (isset($set['catid'])) unset($set['catid']); //例外\r
+ break;\r
+ \r
+ case 'category':\r
+ $params['blogid'] = $this->_getBlogIDFromCatID($params['catid']);\r
+ $baseurl = ($blogid == $params['blogid'] and !$flg_feed) ? $CONF['CategoryURL'] : getBlogURLFromID($params['blogid']);\r
+ \r
+ $set['blogid'] = $params['blogid'];\r
+ $set['catid'] = $params['catid'];\r
+ break;\r
+ \r
+ case 'archivelist':\r
+ if (!$params['blogid']) $params['blogid'] = $CONF['DefaultBlog'];\r
+ $baseurl = ($blogid == $params['blogid'] and !$flg_feed) ? $CONF['ArchiveListURL'] : getBlogURLFromID($params['blogid']);\r
+ \r
+ $set['blogid'] = $params['blogid'];\r
+ if ($this->flg_fancy) {\r
+ $set['archivelist'] = '[[NONE]]'; //キーのみ、値無し(dummy)\r
+ }\r
+ else {\r
+ $set['archivelist'] = $params['blogid'];\r
+ }\r
+ break;\r
+ \r
+ case 'archive':\r
+ $baseurl = ($blogid == $params['blogid'] and !$flg_feed) ? $CONF['ArchiveURL'] : getBlogURLFromID($params['blogid']);\r
+ \r
+ $set['blogid'] = $params['blogid'];\r
+ $set['archive'] = $params['archive'];\r
+ break;\r
+ \r
+ case 'blog':\r
+ $baseurl = ($blogid == $params['blogid'] and !$flg_feed) ? $CONF['BlogURL'] : getBlogURLFromID($params['blogid']);\r
+ \r
+ $set['blogid'] = $params['blogid'];\r
+ break;\r
+ }\r
+ \r
+ //addLinkParams()の変更はコアファイルを書き換えるか、NP_SimpleURL::addLinkParams()を呼ぶかのいずれか\r
+ $data['url'] = $this->addLinkParams($baseurl, $set, '.html', true);\r
+ $data['completed'] = true;\r
+ }\r
+ \r
+ /**\r
+ * add link params\r
+ * \r
+ * 単独でglobalfunctions.phpの addLinkParams() にコピペ・上書きしても動くはず。\r
+ * \r
+ * @static\r
+ * @access public\r
+ * @param $link base link\r
+ * @param $params parameters (assoc array)\r
+ * @param $postfix postfix to add extension like ".html"\r
+ * @param $flg_check flag for event_GenerateURL\r
+ */\r
+ function addLinkParams($link, $params, $postfix='', $flg_check=false)\r
+ {\r
+ global $manager, $CONF, $blog, $blogid;\r
+ static $defBlogURL, $orderbase;\r
+ \r
+ if (! is_array($params) ) return $link;\r
+ \r
+ $blogid_copy = $params['blogid']; //後の処理で消える場合があるのでコピーをとっておく\r
+ \r
+ if ($flg_check) { //GenerateURLからの処理の続き\r
+ if (!$CONF['NP_SimpleURL']['ShowBlogAlways']) {\r
+ if ($defBlogURL == null) $defBlogURL = getBlogURLFromID($CONF['DefaultBlog']);\r
+ \r
+ if ($params['archivelist']) { //archivelistの例外\r
+ unset($params['blogid']);\r
+ }\r
+ else if ($CONF['URLMode'] == 'pathinfo' and \r
+ ($params['blogid'] == $CONF['DefaultBlog'] or //既定のブログ→blogid不要\r
+ $link != $defBlogURL) //既定以外の呼び出しURLはselectBlog()前提→blogid不要\r
+ ) {\r
+ unset($params['blogid']);\r
+ }\r
+ }\r
+ }\r
+ \r
+ if ($CONF['URLMode'] == 'pathinfo') {\r
+ //パラメータの並び順を取得する\r
+ $order = array();\r
+ if (!$orderbase) {\r
+ $orderbase = $CONF['NP_SimpleURL']['URLOrder'];\r
+ asort($orderbase); //優先順位でソート\r
+ }\r
+ foreach (array_keys($orderbase) as $key) $order[$key] = ''; //先にキーをセット\r
+ \r
+ //$paramsに対応するキーのマッピング\r
+ //ここに割り込む必要がないように、外部からのURL拡張は キーを書き換えずに使える名前にすること。\r
+ $keymap = array(\r
+ 'blogid' => $CONF['BlogKey'],\r
+ 'catid' => $CONF['CategoryKey'],\r
+ 'special' => $CONF['SpecialskinKey'],\r
+ 'itemid' => $CONF['ItemKey'],\r
+ 'archivelist' => $CONF['ArchivesKey'],\r
+ 'archive' => $CONF['ArchiveKey'],\r
+ 'memberid' => $CONF['MemberKey'],\r
+ );\r
+ \r
+ //キーや値の書き換え、並び順への追加\r
+ foreach ($params as $key => $value) {\r
+ //blogid, catid, memberid, itemidの書き換え(数値→文字列へ)\r
+ if ($CONF['NP_SimpleURL']['UseAlias']) {\r
+ switch ($key) {\r
+ case 'blogid':\r
+ $value = getBlogAliasFromID($value);\r
+ break;\r
+ case 'catid':\r
+ $value = getCatAliasFromID($value, $blogid_copy);\r
+ break;\r
+ case 'itemid':\r
+ $value = getItemAliasFromID($value);\r
+ break;\r
+ case 'memberid':\r
+ $value = getMemberAliasFromID($value);\r
+ break;\r
+ }\r
+ }\r
+ \r
+ if ($keymap[$key]) $key = $keymap[$key]; //該当キーを$CONF['hogeKey']に書き換え\r
+ $order[$key] = $value; //並び順指定があればそのキーに値を格納。なければ$orderの最後尾に新規追加されていく\r
+ }\r
+ \r
+ //実際にURLを組み立てる\r
+ foreach ($order as $key => $value) {\r
+ if ($value == '') continue;\r
+ \r
+ if ($CONF['NP_SimpleURL']['DropKeys'] and ($key == $CONF['BlogKey'] or $key == $CONF['CategoryKey'])) {\r
+ $link .= ((substr($link, -1) == '/') ? '' : '/') . $value . '/'; //ディレクトリ構造を模して最後を閉じる\r
+ }\r
+ else if ($CONF['NP_SimpleURL']['DropKeys'] and $key == $CONF['ItemKey']) {\r
+ $link .= ((substr($link, -1) == '/') ? '' : '/') . rawurlencode($value);\r
+ }\r
+ else if ($value == '[[NONE]]') { //キーのみ、値無し\r
+ $link .= ((substr($link, -1) == '/') ? '' : '/') . $key;\r
+ }\r
+ else {\r
+ $link .= ((substr($link, -1) == '/') ? '' : '/') . $key . '/' . rawurlencode($value);\r
+ }\r
+ }\r
+ \r
+ $link .= (substr($link, -1) == '/') ? '' : $postfix;\r
+ }\r
+ else { //normal url\r
+ foreach ($params as $param => $value) {\r
+ $link .= ((strpos($link, '?') === false) ? '?' : '&') . $param . '=' . urlencode($value);\r
+ }\r
+ }\r
+ return $link;\r
+ }\r
+ \r
+ /**\r
+ * setter of url order\r
+ * \r
+ * @static\r
+ * @access public\r
+ * @param $key key of the parameter\r
+ * @param $rank rank for order (integer; the smaller number is the higher rank)\r
+ */\r
+ function setURLOrder($key, $rank)\r
+ {\r
+ global $CONF;\r
+ $CONF['NP_SimpleURL']['URLOrder'][$key] = $rank;\r
+ }\r
+ \r
+ \r
+ function doItemVar(&$item, $id, $text='') {\r
+ $id = (int)$id;\r
+ if ($id) {\r
+ $link = createItemLink($id);\r
+ if ($text == '') $text = strip_tags($this->_getDataFromItemID($id, $type='ititle'));\r
+ echo "<a href=\"{$link}\">{$text}</a>";\r
+ }\r
+ }\r
+ \r
+ \r
+ \r
+ /* ----------------- helper methods ----------------- */\r
+ \r
+ function _http301($url)\r
+ {\r
+ header('HTTP/1.1 301 Moved Permanently');\r
+ header('Location: ' . $url);\r
+ exit;\r
+ }\r
+ \r
+ function _http404()\r
+ {\r
+ $language = ereg_replace( '[\\|/]', '', getLanguageName());\r
+ if (file_exists($this->getDirectory().$language.'.php'))\r
+ include_once($this->getDirectory().$language.'.php');\r
+ else\r
+ include_once($this->getDirectory().'english.php');\r
+ \r
+ header('HTTP/1.1 404 Not Found');\r
+ doError(_PLUG_SIMPLEURL_MSG404);\r
+ }\r
+ \r
+ function _isValidURL($url)\r
+ {\r
+ return preg_match('/^https?\:\/\//', $url);\r
+ }\r
+ \r
+ function _quoteSmart($val)\r
+ {\r
+ if (get_magic_quotes_gpc()) $val = stripslashes($val);\r
+ if (preg_match('/^[0-9]+$/', $val)) {\r
+ $qmark = '';\r
+ }\r
+ else {\r
+ $qmark = '"';\r
+ $val = mysql_real_escape_string($val);\r
+ }\r
+ return $qmark . $val . $qmark;\r
+ }\r
+ \r
+ function _getBlogIDFromAlias($name)\r
+ {\r
+ static $buff;\r
+ \r
+ if (! isset($buff)) {\r
+ $buff[$name] = quickQuery('SELECT bnumber as result FROM ' . sql_table('blog') . \r
+ ' WHERE bshortname="' . mysql_real_escape_string($name) . '"');\r
+ }\r
+ return ($buff[$name]) ? $buff[$name] : 0;\r
+ }\r
+ \r
+ function _getMemberIDFromAlias($name)\r
+ {\r
+ static $buff;\r
+ \r
+ $name = str_replace('_', ' ', $name);\r
+ if (!$buff[$name]) {\r
+ $buff[$name] = quickQuery('SELECT mnumber as result FROM ' . sql_table('member') . \r
+ ' WHERE mname="' . mysql_real_escape_string($name) .'"');\r
+ }\r
+ return ($buff[$name]) ? $buff[$name] : 0;\r
+ }\r
+ \r
+ function _getCatIDFromAlias($name)\r
+ {\r
+ global $blogid;\r
+ static $buff;\r
+ \r
+ if (! isset($buff)) {\r
+ //$buff = array_flip($this->getAllCategoryOptions('cshortname'));\r
+ $query = 'SELECT catid, cshortname FROM ' . sql_table('plug_simpleurl');\r
+ if ($blogid) $query .=' WHERE blogid='. (int)$blogid;\r
+ $res = sql_query($query);\r
+ \r
+ while($data = mysql_fetch_assoc($res)) {\r
+ $buff[ $data['cshortname'] ] = $data['catid'];\r
+ }\r
+ }\r
+ \r
+ return ($buff[$name]) ? $buff[$name] : 0;\r
+ }\r
+ \r
+ function _getItemIDFromAlias($name)\r
+ {\r
+ /*static $buff;\r
+ \r
+ $name = urldecode($name);\r
+ if (!$buff[$name]) {\r
+ $buff[$name] = quickQuery('SELECT inumber as result FROM ' . sql_table('item') . \r
+ ' WHERE ititle="' . mysql_real_escape_string($name) . '"');\r
+ }\r
+ return ($buff[$name]) ? $buff[$name] : 0;\r
+ */\r
+ if (preg_match('/-([0-9]+?)$/', $name, $m)) {\r
+ return (int)$m[1];\r
+ }\r
+ else {\r
+ return 0;\r
+ }\r
+ }\r
+ \r
+ function _getDataFromItemID($itemid, $type='')\r
+ {\r
+ $itemid = (int)$itemid;\r
+ \r
+ if (!$this->arr_item[$itemid]) {\r
+ $res = sql_query('SELECT iblog, icat, ititle FROM ' . sql_table('item') . ' WHERE inumber=' . $itemid);\r
+ if (mysql_num_rows($res)) {\r
+ $this->arr_item[$itemid] = mysql_fetch_assoc($res);\r
+ }\r
+ }\r
+ if ($type) return $this->arr_item[$itemid][$type];\r
+ else return $this->arr_item[$itemid];\r
+ }\r
+ \r
+ function _getBlogIDFromItemID($itemid)\r
+ {\r
+ return $this->_getDataFromItemID($itemid, 'iblog');\r
+ }\r
+ \r
+ function _getCatIDFromItemID($itemid)\r
+ {\r
+ return $this->_getDataFromItemID($itemid, 'icat');\r
+ }\r
+ \r
+ function _getBlogIDFromCatID($catid)\r
+ {\r
+ static $buff;\r
+ \r
+ $catid = (int)$catid;\r
+ if (! $buff[$catid]) {\r
+ $res = sql_query('SELECT catid, cblog FROM ' . sql_table('category'));\r
+ if (mysql_num_rows($res)) {\r
+ while ($data = mysql_fetch_assoc($res)) {\r
+ $buff[ $data['catid'] ] = $data['cblog'];\r
+ }\r
+ }\r
+ }\r
+ return $buff[$catid];\r
+ }\r
+ \r
+ function _getCatNameFromID($id)\r
+ {\r
+ return quickQuery('SELECT cname as result FROM '. sql_table('category') .' WHERE catid='. (int)$id);\r
+ }\r
+ \r
+ function _canEdit($type='admin')\r
+ {\r
+ global $member;\r
+ \r
+ $query = 'SELECT * FROM '.sql_table('team').' WHERE tmember='. $member->getID();\r
+ if ($type == 'admin') $query .= ' and tadmin=1';\r
+ return (mysql_num_rows(sql_query($query)) != 0);\r
+ }\r
+ \r
+ \r
+ /* ----------------- methods for admin area ----------------- */\r
+ \r
+ function _makeAdminArea(&$oPluginAdmin)\r
+ {\r
+ global $manager, $member;\r
+ \r
+ $adminurl = $this->getAdminURL();\r
+ \r
+ if (!$member->isLoggedIn() or !$this->_canEdit()) {\r
+ $oPluginAdmin->start();\r
+ echo '<p>' . _ERROR_DISALLOWED . '</p>';\r
+ $oPluginAdmin->end();\r
+ exit;\r
+ }\r
+ \r
+//<script type='text/javascript' src='../../javascript/numbercheck.js'></script>\r
+ $oPluginAdmin->start("\r
+<script type='text/javascript'>\r
+<!--\r
+\r
+function confirm_check(message) {\r
+ if( confirm(message) ){\r
+ sent = true;\r
+ return true;\r
+ }\r
+ else {\r
+ return false;\r
+ }\r
+}\r
+\r
+// -->\r
+</script>\r
+<style type='text/css'>\r
+<!--\r
+p.message {\r
+ font-weight: bold;\r
+ color: #c00;\r
+}\r
+form.button {\r
+ display: inline;\r
+}\r
+table.group {\r
+ margin: 5px 0;\r
+}\r
+table.group td {\r
+ background-color: #ddd;\r
+}\r
+table.link {\r
+ margin: 0;\r
+}\r
+table.link th {\r
+ /*background-color: #ddd;*/\r
+}\r
+table.link td.stripe {\r
+ background-color: #eee;\r
+}\r
+span.idlabel {\r
+ border: 1px solid #666;\r
+ padding: 1px 2px;\r
+ background-color: #999;\r
+ color: white;\r
+}\r
+-->\r
+</style>\r
+");\r
+ \r
+ echo "<h2>SimpleURL</h2>";\r
+ \r
+ $action = requestVar('action');\r
+ $actions = array (\r
+ 'index',\r
+ 'update',\r
+ );\r
+ \r
+ if ($action == '') {\r
+ $this->_makeCatAliasForm();\r
+ }\r
+ else if (in_array($action, $actions)) { \r
+ if (!$manager->checkTicket()) {\r
+ echo '<p class="error">Error: ' . _ERROR_BADTICKET . '</p>';\r
+ } \r
+ else {\r
+ switch ($action) {\r
+ case 'index':\r
+ $this->_makeCatAliasForm();\r
+ break;\r
+ case 'update':\r
+ $isok = $this->_updateCatAlias();\r
+ if ($isok) echo '<p class="message">Updated successfully.</p>';\r
+ else echo '<p class="error">Error: Update failed (in some records).</p>';\r
+ \r
+ $this->_makeCatAliasForm();\r
+ break;\r
+ }\r
+ }\r
+ } \r
+ else {\r
+ echo '<p class="error">Error: Invalid action type.</p>';\r
+ }\r
+ $oPluginAdmin->end();\r
+ }\r
+ \r
+ function _makeCatAliasForm()\r
+ {\r
+ global $manager;\r
+ \r
+ $adminurl = $this->getAdminURL();\r
+ $action = 'update';\r
+ \r
+ echo <<<OUT\r
+<h3>Setting: Category Alias</h3>\r
+<table>\r
+<form method="post" action="{$adminurl}">\r
+<input type="hidden" name="action" value="{$action}" />\r
+<input type="hidden" name="type" value="categoryalias" />\r
+OUT;\r
+ $manager->addTicketHidden();\r
+ echo <<<OUT\r
+<tr>\r
+ <th>Blog</th><th>Category</th><th>Alias Name [0-9a-z_-]</th>\r
+</tr>\r
+OUT;\r
+ $data = getCatAliasesFromDB();\r
+ foreach ($data as $blogid => $bdata) {\r
+ $blogname = htmlspecialchars(getBlogNameFromID($blogid));\r
+ foreach ($bdata as $catid => $cshortname) {\r
+ $catname = htmlspecialchars($this->_getCatNameFromID($catid));\r
+ echo <<<OUT\r
+<tr>\r
+ <td><span class="idlabel">ID:{$blogid}</span> {$blogname}</td><td><span class="idlabel">ID:{$catid}</span> {$catname}</td><td><input type="text" name="catids[{$catid}]" value="{$cshortname}" size="20" /></td>\r
+</tr>\r
+OUT;\r
+ }\r
+ }\r
+ echo <<<OUT\r
+<tr>\r
+ <th colspan="3" style="text-align:center"><input type="submit" value="Submit"></th>\r
+</tr>\r
+</form>\r
+</table>\r
+\r
+OUT;\r
+ }\r
+ \r
+ function _updateCatAlias()\r
+ {\r
+ if (!is_array($_POST['catids'])) return false;\r
+ \r
+ $err = 0;\r
+ foreach ($_POST['catids'] as $catid => $cshortname) {\r
+ $cshortname = strtolower($cshortname);\r
+ $cshortname = preg_replace('/[^0-9a-z_-]/', '', $cshortname);\r
+ if ($cshortname == '') {\r
+ $err++;\r
+ continue;\r
+ }\r
+ $query = sprintf("UPDATE %s SET cshortname=%s WHERE catid=%d",\r
+ sql_table("plug_simpleurl"),\r
+ $this->_quoteSmart($cshortname),\r
+ $this->_quoteSmart($catid)\r
+ );\r
+ $res = sql_query($query);\r
+ if (!$res) $err++;\r
+ }\r
+ return ($err == 0);\r
+ }\r
+ \r
+}\r
+?>\r