スパム対策として書込み時にID/PWを要求されますが、ローマ字で ほげ/ホゲ で書き込めるようになります。

#contents
*VIMでPukiWikiの閲覧、編集を可能にする。 [#va2bc1d3]
// ブラウザーからみて整形済みテキストに見えるようにソースコードは :%s/^/ / してから貼り付けてあります。
// このコメント部分はブラウザーからは見えません。
対象となるPukiWikiのバージョンは 1.4.x で euc-jp で運用している必要があります。

インストール方法
+vim.php を index.php と同じところに置く。
+vim.inc.php を plugin ディレクトリーへ置く。
+以上!
後は、 vim.php の URL を vim から :e で開くだけです。
 Ex.
   :e http://vim.mydns.jp/vim.php

書き込む際にはKoRoNさんが作成されたvimスクリプトが必要。ダウンロードは
[[こちら:http://cvs.kaoriya.net/svn/kaoriya/vimscript/misc/plugin/pukiwiki_edit.vim]]
// vim用にも貼り付けておきます。下のURL上で <c-w>f で開けます。
// http://cvs.kaoriya.net/svn/kaoriya/vimscript/misc/plugin/pukiwiki_edit.vim

[[KoRoN]]さんに感謝します。

:2005/03/20|
書き込み用スクリプト ''pukiwiki_edit.vim'' を 最新版の PHP スクリプトに合わせて改良してあります。
ソースコードはこのページの下に貼り付けてあります。

読み書きにはwgetが必須です。読込みにはVimのnetrw.vimプラグインが内部でwgetを利用しています。書込みにはwgetのPOST機能を使用していますので、wgetのバージョンは1.9.1以降である必要があります。[[参考情報:http://hnw.jp/documents/unixmemo/wget.html]]


**変更履歴 [#wfebe6b5]

***2005/03/20 [#g482168d]
-全部書き直し。
-ファイル名の変更 dump4vim.inc.php -> vim.inc.php
-以前は 表示用ページ -> 編集用ページ となっていたのを表示したらそのまま編集できるように変更。
-ページが凍結されていたり、毎回動的に表示するようなページの modeline には noma を付加する。
-modeline に noma が有る時に :se ma して編集されても pukiwiki_edit.vim で modeline をみてエラーを吐くようにした。
-書込む時に pukiwiki_edit.vim で (yes/no) 確認するように変更。
-書き込んだ後はレスポンスで置き換えるように pukiwiki_edit.vim を変更。
-PHPスクリプトで本文が何行目から始まるのかを1行目の1文字目(modeline の前)に吐き出すように変更。
-上記変更に伴い、pukiwiki_edit.vim で書き込む時に本文をエンコードする位置をmodelineの前から取得するように変更。
-当サイトに依存した部分(tipsやfaqのダンプ)を簡単に無効に出来るように変更。
-日本語のページの閲覧、編集が出来るように改造。
-ページの検索機能を実装。
-ページの新規作成機能を実装。
-最終更新日が確認できるページを実装。

これでとりあえず、何とか常用出来るレベルになったかなぁ…

----

#comment

***2005/03/16 [#o26788e4]
-とりあえず、現状何とか動く物を公開。

----
#comment

**ソースコード [#c433edc7]
*** pukiwiki_edit.vim [#m56ecb20]
Last Change: &new{2005-03-20 19:00:40 (日)};
 " vim:set ts=8 sts=2 sw=2 tw=0 fdm=marker:
 "
 " pukiwiki_edit.vim - PukiWiki edit plugin.
 "
 " Last Change: 15-Mar-2005.
 " Written By:  MURAOKA Taro <koron@tka.att.ne.jp>
 
 if exists('plugin_pukiwiki_edit_disable')
   finish
 endif
 
 let g:pukiwiki_edit_encoding = "euc-jp"
 
 augroup PukiwikiEdit
   autocmd!
   autocmd BufWriteCmd http://*/vim.php* call s:BufWriteCmd()
 augroup END
 
 function! s:BufWriteCmd()
   if &modified != 0
     let modeline = getline(1)
     if modeline =~ 'noma'
       echohl WarningMsg
       echo "PukiWiki: Cannot make changes, 'modifiable' is off"
       set nomodified
       return 0
     endif
     let last_confirm = input('really write it? (yes/no)')
     if last_confirm =~ '^\cy'
       call s:EncodePukiwiki()
       let tmp_body = tempname()
       silent! execute "%write! " . tmp_body
       let cmd = "wget -qO - --post-file=" . tmp_body . " " . expand('%')
       let result = system(cmd)
       let result = iconv(result, g:pukiwiki_edit_encoding, &encoding)
       execute "normal! ggdGi" . result
       call delete(tmp_body)
     endif
     set nomodified
   endif
 endfunction
 
 function! s:EncodePukiwiki()
   let body_pos = getline(1)[col(1)]
   execute "normal! " . body_pos . "G"
   silent! .,$s/[%&+]/\=s:EncodeChar(submatch(0))/g
 endfunction
 
 function! s:EncodeChar(ch)
   let n = char2nr(a:ch[0])
   let r = ""
   while 1
     let r = "0123456789ABCDEF"[n % 16] . r
     let n = n / 16
     if n == 0
       break
     endif
   endwhile
   return '%'.(strlen(r) < 2 ? '0' : '').r
 endfunction

*** vim.php [#caeeb3be]
Last Change: &new{2005-03-20 19:00:40 (日)};
 <?php
 $_GET['cmd'] = $_POST['cmd'] = 'vim';
 require_once('index.php');
 ?>

*** vim.inc.php [#v5511d11]
Last Change: &new{2005-03-20 19:00:40 (日)};
 <?php // vim: set ts=4 sw=4 sts=4 fdm=marker noet:
 error_reporting(E_ALL);
 // {{{1 plugin_vim_init() 設定
 
 function plugin_vim_init()
 {
 	global $vim;
 
 	$vim = array(
 		// vim用の FrontPage を指定する、存在しない場合には
 		// ブラウザ用の pukiwiki.ini.php の $defaultpage が表示される。
 		'defaultpage' => 'FrontPage4Vim',
 
 		// :syntax on の場合、サイトで扱っているテーマに合わせて変更する。
 		// VimWikiの場合には扱っているテーマがVimに関することなのでhelpに
 		// してあります。指定しないとft=phpになるので適当に調整してください。
 		'filetype'    => 'help',
 
 		// vimが文字コードの判定に失敗しないようにする為の物です。
 		'encode_hint' => '燕の往来',
 
 		// どこからが本文なのかを表す文字
 		'boundary'    => '----------------------------------------------------------------------',
 
 		// 書き込む際に boundary を除去するための正規表現
 		'strip_boundary_regex' => '/^-+/',
 
 		// 編集出来ないページに表示する文字
 		'msg_not_editable' => '===== Not Editable =====',
 
 		// http://vim.mydns.jp/ のサイト構成に依存した機能を使うか。
 		// PukiWiki の Tracker プラグインを使ったページをダンプする機能
 		// vim.php/cmd/dump/*
 		// 1: 使う 0: 使わない
 		'is_vimwiki'  => 1
 	);
 }
 
 // {{{1 plugin_vim_action() メイン
 
 function plugin_vim_action()
 {
 	global $defaultpage, $page_title, $script, $vars;
 	global $vim;
 
 	if( basename( $script ) != 'vim.php' )
 	{
 		return array(
 			'msg' => 'vim.php からアクセスして下さい。',
 			'body' => 'このプラグインは vim.php 専用です。<br />
 				vim.php からアクセスして下さい。');
 	}
 
 	$path_info = '';
 	if( ! empty( $_SERVER['PATH_INFO'] ) )
 		$path_info = $_SERVER['PATH_INFO'];
 
 	$path_info = substr( $path_info, 1);
 
 	// 出力する物は全てこの $response に入れる。
 	$response = array();
 
 	// {{{2 POST
 	if( $_SERVER['REQUEST_METHOD'] == 'POST' )
 	{
 		if( empty( $vars['exec'] ) )
 		{
 			$vars['exec'] = '';
 		}
 		switch( $vars['exec'] )
 		{
 			case 'write':
 				$response = plugin_vim_exec_write( $response );
 				break;
 			case 'new':
 				$response = plugin_vim_exec_new( $response );
 				break;
 			case 'search':
 				$response = plugin_vim_exec_search( $response );
 				break;
 			default:
 				$response['is_editable'] = false;
 				$response['header'][] = "|{$page_title}| {$script}\n"; // トップページのURL
 				$response['header'][] = "|{$path_info}| {$script}/{$path_info}\n"; // リロード用
 				$response['body'] = "\n不正なコマンドを受取りました。\n\n{$script}";
 				break;
 		}
 
 		plugin_vim_show_page( $response );
 		exit;
 	}
 
 	// {{{2 GET
 	// {{{3 cmd/hoge 用の処理
 	if( preg_match('/^cmd\/.*$/', $path_info) )
 	{
 		$response['header'][] = "|{$page_title}| {$script}\n"; // トップページのURL
 		$response['header'][] = "|{$path_info}| {$script}/{$path_info}\n"; // リロード用
 		$cmd = split('/', $path_info);
 		switch( $cmd[1] )
 		{
 			case 'cmdlist':
 				$response = plugin_vim_cmd_cmdlist( $response );
 				break;
 			case 'pagelist':
 				$response = plugin_vim_cmd_pagelist( $response );
 				break;
 			case 'resent':
 				$response = plugin_vim_cmd_resent( $response );
 				break;
 			case 'new':
 				$response = plugin_vim_cmd_new( $response );
 				break;
 			case 'search':
 				$response = plugin_vim_cmd_search( $response );
 				break;
 			default:
 				// XXX VimWikiのサイト構成に依存した機能 vim.php/cmd/dump/*
 				if( $vim['is_vimwiki'] && $cmd[1] == 'dump'
 					&& ! empty( $cmd[2] ) && ( $cmd[2] == 'tips' || $cmd[2] == 'faq'
 						|| $cmd[2] == 'RegexQA' || $cmd[2] == 'scripts' ) )
 				{
 					$response = plugin_vim_cmd_dump( $response, $cmd[2] );
 					break;
 				}
 				else
 				{
 					$response['is_editable'] = false;
 					$response['body'] = "\n不正なコマンドを受取りました。\n\n{$script}";
 					break;
 				}
 		}
 
 		plugin_vim_show_page( $response );
 		exit;
 
 	}
 
 	// {{{3 単一ページの表示
 	// vim用defaultpageが無かったらPukiWikiブラウザ用のを表示
 	if( empty( $path_info ) )
 	{
 		if( is_page( $vim['defaultpage'] ) )
 		{
 			$path_info = $vim['defaultpage'];
 		}
 		else
 		{
 			$path_info = $defaultpage;
 		}
 	}
 
 	// 日本語対応 fixme もっと良い方法が有ったら教えて下さい。
 	if( ! is_page( $path_info ) )
 	{
 		$dec_page = decode( $path_info );
 		if( is_page( $dec_page ) )
 		{
 			$path_info = $dec_page;
 		}
 	}
 
 	$source = join('', get_source( $path_info ) );
 
 	$response['is_editable'] = false;
 	$response['header'][] = "|{$page_title}| {$script}\n"; // トップページのURL
 	$enc_page = plugin_vim_get_enc_page( $path_info );
 	$response['header'][] = "|{$path_info}| {$script}/{$enc_page}\n"; // リロード用
 	$response['header'][] = "|cmdlist| {$script}/cmd/cmdlist\n"; // コマンド一覧
 
 	if( is_editable( $path_info ) )
 	{
 		$response['is_editable'] = true;
 		$digest = md5( $source );
 		$response['header'][] = "&encode_hint=ぷ&exec=write&page={$path_info}&digest={$digest}&msg=\n";
 		$response['header'][] = "{$vim['boundary']}\n";
 	}
 
 	$response['body'] = trim( $source );
 
 	plugin_vim_show_page( $response );
 	exit;
 }
 
 // {{{1 plugin_vim_exec_write() 書込み
 // この関数の元ネタは plugin/edit.inc.php#plugin_edit_write()
 function plugin_vim_exec_write( $response )
 {
 	global $vars, $script, $page_title, $vim;
 
 	$page = isset($vars['page']) ? $vars['page'] : '';
 
 	$vars['msg'] = trim( $vars['msg'] );
 	$vars['msg'] = preg_replace( $vim['strip_boundary_regex'], '', $vars['msg'] );
 	// 手書きの#freezeを削除
 	$vars['msg'] = preg_replace( '/^#freeze\s*$/im', '', $vars['msg'] );
 	$postdata = $postdata_input = $vars['msg'];
 
 	$oldpagesrc = join('', get_source($page));
 	$oldpagemd5 = md5($oldpagesrc);
 
 	if ( ! isset($vars['digest']) || $vars['digest'] != $oldpagemd5)
 	{
 		// 更新の衝突が発生。
 		$response['body'] = "\n更新の衝突が発生しました。\n貴方が書き込んだ内容が失われました。";
 	}
 	else
 	{
 		// 書き込み
 		if ($postdata)
 		{
 			if( ! is_editable( $page ) )
 			{
 				$response['body'] = "\nページ名 ''{$page}'' は書き込みできません。";
 			}
 			else
 			{
 				page_write($page, $postdata, false); // しばらくは常にage
 				$response['body'] = "\n更新完了。";
 			}
 		}
 		else
 		{
 			// ページの削除
 			$response['body'] = "\nVIMからのページの削除は禁止にしています。";
 		}
 	}
 
 	$enc_page = plugin_vim_get_enc_page( $page );
 	$response['is_editable'] = false;
 	$response['body'] .= "\n\n{$script}/{$enc_page}";
 	$response['header'][] = "|{$page_title}| {$script}\n"; // トップページのURL
 	$response['header'][] = "|{$page}| {$script}/{$enc_page}\n"; // リロード用
 
 	return $response;
 }
 
 // {{{1 plugin_vim_exec_new() 新規作成用
 
 function plugin_vim_exec_new( $response )
 {
 	global $vars, $script, $page_title, $vim;
 
 	$vars['pagename'] = trim( $vars["\npagename"] );
 	$response['is_editable'] = true;
 	$response['header'][] = "|{$page_title}| {$script}\n"; // トップページのURL
 
 	$source = join('', get_source( $vars['pagename'] ) );
 	$enc_page = plugin_vim_get_enc_page( $vars['pagename'] );
 	$response['header'][] = "|{$vars['pagename']}| {$script}/{$enc_page}\n"; // リロード用
 	$response['header'][] = "|cmdlist| {$script}/cmd/cmdlist\n"; // コマンド一覧
 	$digest = md5( $source );
 	$response['header'][] = "&encode_hint=ぷ&exec=write&page={$vars['pagename']}&digest={$digest}&msg=\n";
 	$response['header'][] = "{$vim['boundary']}\n";
 	$response['body'] = "";
 
 	return $response;
 }
 
 // {{{1 plugin_vim_exec_search() 検索結果を表示
 
 function plugin_vim_exec_search( $response )
 {
 	global $vars, $script, $page_title;
 
 	$vars['word'] = trim($vars["\nword"]);
 	$response['is_editable'] = false;
 
 	$response['header'][] = "|{$page_title}| {$script}\n"; // トップページのURL
 	$response['header'][] = "|search| {$script}/cmd/search\n";
 
 	$all_page_name = get_existpages();
 	$total_page = count( $all_page_name );
 
 	$result = do_search( $vars["word"], 'AND', true );
 	sort( $result );
 	$hit_count = count( $result );
 
 	$response['body'] = "\nキーワード '{$vars['word']}' を含むページは\n";
 	$response['body'] .= "{$total_page} ページ中 {$hit_count} ページ見つかりました。\n\n";
 
 	foreach( $result as $page )
 	{
 		$enc_page = plugin_vim_get_enc_page( $page );
 		$response['body'] .= "{$page}\n{$script}/{$enc_page}\n\n";
 	}
 
 	return $response;
 }
 
 // {{{1 plugin_vim_cmd_dump() VimWiki 用一覧表示 tips 一覧とか
 
 function plugin_vim_cmd_dump( $response, $target )
 {
 	global $script, $page_title;
 
 	$response['is_editable'] = false;
 
 	$response['body'] = "";
 
 	foreach( get_existpages() as $_page )
 	{
 		if( ! preg_match("/^{$target}\//", $_page ) )
 			continue;
 
 		$lines = get_source( $_page);
 
 		$lines = array_slice( $lines, 2, -3 );
 
 		$response['body'] .= "==============================================================================\n";
 		$response['body'] .= "{"."{{1 *{$_page}";
 		$lines[0] = "{$lines[0]}{$script}/{$_page}\n";
 
 		foreach( $lines as $line )
 		{
 			if( preg_match('/^-ページ.*$/', $line ) )
 				continue;
 
 			if( preg_match('/^-バージョン.*$/', $line ) )
 				continue;
 
 			$line = preg_replace('/\[#[0-9a-z]{8}\]/', '', $line);
 
 			$line = preg_replace('/ +$/', '', $line);
 
 			$line = preg_replace('/\~$/', '', $line);
 
 			$response['body'] .= $line;
 		}
 	}
 
 	return $response;
 }
 
 // {{{1 plugin_vim_cmd_cmdlist() コマンドの一覧
 
 function plugin_vim_cmd_cmdlist( $response )
 {
 	global $script;
 
 	$response['is_editable'] = false;
 	$response['body'] = "
 ページ一覧
 {$script}/cmd/pagelist
 
 最新のXX件
 {$script}/cmd/resent
 
 検索
 {$script}/cmd/search
 
 新規作成
 {$script}/cmd/new
 ";
 
 	return $response;
 
 }
 
 // {{{1 plugin_vim_cmd_pagelist() ページの一覧
 
 function plugin_vim_cmd_pagelist( $response )
 {
 
 	global $script;
 
 	$response['is_editable'] = false;
 	$response['body'] = "\n";
 	$pages = get_existpages();
 	sort( $pages );
 	foreach( $pages as $page )
 	{
 		$enc_page = plugin_vim_get_enc_page( $page );
 		$response['body'] .= "{$page}\n{$script}/{$enc_page}\n\n";
 	}
 	$response['body'] .= "\n";
 
 	return $response;
 }
 
 // {{{1 plugin_vim_cmd_resent() 最終更新
 // この関数の元ネタは plugin/recent.inc.php
 function plugin_vim_cmd_resent( $response )
 {
 	global $script, $date_format;
 
 	$f = CACHE_DIR . 'recent.dat';
 
 	$response['is_editable'] = false;
 
 	$lines = file( $f );
 
 	$date = $response['body'] = '';
 	foreach ($lines as $line) {
 		list($time, $page) = explode("\t", rtrim($line));
 		$_date = get_date($date_format, $time);
 		if ($date != $_date) {
 			$date = $_date;
 			$response['body'] .= "===== $date =====\n";
 		}
 		$s_page = htmlspecialchars($page);
 		$r_page = rawurlencode($page);
 		$pg_passage = get_pg_passage($page, FALSE);
 		$enc_page = plugin_vim_get_enc_page( $s_page );
 		$response['body'] .= "{$s_page} {$pg_passage}\n{$script}/{$enc_page}\n\n";
 	}
 
 	return $response;
 }
 
 // {{{1 plugin_vim_cmd_new() 新規作成用
 
 function plugin_vim_cmd_new( $response )
 {
 	$response['is_editable'] = true;
 
 	$response['header'][] = "&exec=new&encode_hint=ぷ&\npagename=";
 	$response['body'] = "";
 
 	return $response;
 }
 
 // {{{1 plugin_vim_cmd_search() 検索用ページを表示する
 
 function plugin_vim_cmd_search( $response )
 {
 	$response['is_editable'] = true;
 
 	$response['header'][] = "&exec=search&encode_hint=ぷ&\nword=";
 	$response['body'] = "";
 
 	return $response;
 }
 
 // {{{1 plugin_vim_get_enc_page() 日本語ページ対策
 // 非アスキー文字が含まれていたらエンコードして返す。
 // 環境変数 PATH_INFO にマルチバイトが渡せない?から
 // Windows の vim だと確実に化ける… orz
 // vimは : を含むURLを開いてくれないからその場合もエンコードする
 function plugin_vim_get_enc_page( $page )
 {
 	if( preg_match('/[^\t -~]|:/', $page) )
 	{
 		$page = encode( $page );
 	}
 
 	return $page;
 }
 
 // {{{1 plugin_vim_show_page() 表示 出力は全てここで行う。
 
 function plugin_vim_show_page( $response )
 {
 	global $vim;
 
 	// 書込み時にvimスクリプトが何処からエンコードすればよいのかを計算
 	// pukiwiki_edit.vim は1行目の1文字目で判断するようにしてある。
 	$body_pos = count( $response['header'] ) + 2;
 
 	// vim 用 modeline を生成
 	$modeline = "{$body_pos} vim: set ssl fdm=marker";
 	$modeline .= " ft={$vim['filetype']}";
 
 	if( ! $response['is_editable'] )
 	{
 		$modeline .= " noma ";
 		$response['header'][] = "{$vim['msg_not_editable']}\n";
 	}
 	else
 	{
 		$modeline .= " ma ";
 	}
 	
 	$modeline .= ": {$vim['encode_hint']}\n";
 
 	// レスポンス書出し
 	header("Content-type: text/plain");
 
 	echo $modeline;
 
 	foreach( $response['header'] as $header )
 		echo $header;
 
 	echo $response['body'];
 
 	exit;
 }
 
 ?>

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS