ほぼ完成しました.
いま実地で色々とテストをしながら確かめています.
http://www.suzuka-ct.ac.jp/mech/moodle/course/view.php?id=30
ゲストで入室可能です.
”fsconverter:まとめ”のWikiに記載されている”fsconverter修正箇所一覧"にしたがってソースを修正して下さい.これで,日本語フォルダ名/ファイル名をmoodleで(かなり)使えるようになります.ただし,moodle1.8をベースとして開発を行なっていますので,他のバージョンですと修正箇所が異なる可能性もあります.
特に日本語Windowsをサーバとしているサイトではフォルダ名,ファイル名をS-JISでファイルシステムが管理するように設定できますので,エクスプローラを用いてファイルやフォルダの管理を行なうことも可能です(データベースとの整合性を考えるとお勧めはできませんが).
ちなみにWindowsXP ProfessionalをサーバOSとして利用している当方のサイトでは,UTF-8で作成した(つまり化ける)フォルダが原因で定時バックアップに失敗する問題がありましたが,この問題も解決しました.
とりあえずはご報告まで.使い方,メリットなどはまた時間のあるときにまとめます.
修正箇所はかなり多いです.ある程度の覚悟が必要です.
(メリットが勝りますが!)
1.コースの短縮名にマルチバイトを用いた場合にバックアップ・リストアが正常に機能しない(対策済み)
2.IEでフォルダを開けない(一部,サブフォルダの扱いに問題が残っているが大筋OK)
本サイトへのアクセスがゲストの場合,フォーラムへの書き込みができませんので,期間限定で以下のアカウントを作成しました.自己登録も可能にしました.
アカウント: fsuser
パスワード:fsconverter
http://narita.mech.suzuka-ct.ac.jp/moodle/course/view.php?id=30
コースファイルをzipする前に一時フォルダにファイルとフォルダをコピーする単純な処理なので,ファイルシステムに依存しないかな,と思って適用を行なわなかったのですが,時と場合によって問題があったようです.修正箇所を極力少なくしようと考えて意図的に放置していたのですが,安全のために対策を行ないました.
2007年6月27日現在の最新のmoodle1.8.1+をfs_moodle化したパッケージを
http://www.suzuka-ct.ac.jp/mech/moodle/mod/resource/view.php?id=331
の最新版のフォルダに公開しました.
勝手ながら,フォルダ名/ファイル名に半角カッコなどの文字が使用可能とする修正も適用してあります.もし,安全を考えてこの処理を適用したくない方は,lib/moodlelib.php中の4145近辺をオリジナルに戻して下さい.詳しくは以下のフォーラムを参照して下さい.
http://moodle.org/mod/forum/discuss.php?d=74713
http://www.suzuka-ct.ac.jp/mech/moodle/mod/resource/view.php?id=331
もし5週分しかバックアップファイルを保存しない設定になっているにも関わらず,コースのbackupdataフォルダ内に古いバックアップデータが残っていて,HDDの残量に悪影響を与えている場合は,fs_moodleを0.7dにアップデートして下さい.
(道理で,近頃,HDDの残量が急激に少なくなってきた訳です)
五月女@信州大学です.
fs_moodleを利用中気づいたのですが,
admin/delete.php中65行目付近
// if (rmdir($fullfile)) { // (FS_CONVERTER) if (rs_rmdir($fullfile)) { // (FS_CONVERTER)は
// if (rmdir($fullfile)) { // (FS_CONVERTER)
if (fs_rmdir($fullfile)) { // (FS_CONVERTER)
のtypoではないでしょうか?fs_moodle07fにて確認しました.
それにしてもfs_moodle良いですね
すばらしいものを公開していただき感謝します.
私もこれまで独自にMoodleの拡張をしながら日本語ファイル名対応を行っていたのですが,
WindowsXP&VistaからMacOSX,Firefox,Safari,IE6,IE7の混在環境への対応で頭を悩ませていました.
さきほどからfs_moodleを触らせていただき,出来が良いので感動しました.
ただ,何件か不具合も見つけてますので.またご連絡させていただきます.
fs_moode0.7f上でいくつかのパターンか試してみた所,次のような問題がありました.
再現環境は,
* クライアント
o MacOSX10.5 firefox2
o MacOSX10.5 Safari3
o WinXP IE6
o WinXP firefox2
* サーバ
o CentOS 4.5 2.6.9-55.0.9.ELsmp
o PHP 5.2.4
o Apache 2.2.6
o MySQL 5.1.22-rc
* fs_converter
o $fsCFG->fsCharset = 'UTF-8';
o $fsCFG->oldfsCharset = 'UTF-8';
となっています.
試したパターンは
1. MacOSX 10.5でファイル・ディレクトリ作成,標準機能で圧縮,Safari3でアップロード,fs_moodleで展開
2. MacOSX 10.5でファイル・ディレクトリ作成,標準機能で圧縮,Firefox2でアップロード,fs_moodleで展開
3. WinXPでファイル・ディレクトリ作成,標準機能で圧縮,IE6でアップロード,fs_moodleで展開
4. WinXPでファイル・ディレクトリ作成,標準機能で圧縮,Firefox2でアップロード,fs_moodleで展開
の4パターンです.
また,それぞれのファイル・ディレクトリは
* 機種依存文字(丸囲みの数字やローマ数字)
* 半角カタカナ
* 問題のありそうな文字(現在絞り込み中)
といった文字をファイル名に含めました.
これら4パターンで展開したファイルを,Mac,WinXPのそれぞれのクライアントから表示した時にどういった動作をするのか試しました.
パターン1,パターン2について
MacでSafariから利用した場合は表示,ダウンロード,その後の解凍等に問題ありませんでした.
MacでFirefoxから利用した場合に,機種依存文字が”!”や”?”と表示されてしまいましたが,ダウンロード後のファイル名や解凍したファイル名は正常でした.
WinXPでIE6から利用した場合,表示に問題はありませんが,ダインロードしたファイルの機種依存文字が文字化けし,正常に解凍できませんでした.
WinXPでFirefoxから利用した場合,表示に問題はなく,ダウンロードしたファイルも正常ですが,解凍後のファイルが全て文字化けしました.
(解凍時の文字化け問題は,以前白井先生がご指摘されていたMoodle上で圧縮したファイルの文字化け問題と原因は同じだと思います.)
パターン3,パターン4について
まず,アップロード・fs_moodleで展開後のファイル名をサーバ上で確認した所,機種依存文字が”?”と置き換わって保存されてしまう問題がありました.
MacでSafariとFirefoxから利用した場合,上記問題以外は表示,ダウンロード,その後の解凍共に問題なく動作しました.
WinXPでIE6から利用した場合,問題のありそうな文字列が,正常に表示はされるものの,ダウンロードで文字化けしてしまう問題がありました.解凍は正常に行え,文字化けもありませんでした.
WinXPでFirefoxから利用した場合,表示,ダウンロード,その後の解凍等に問題ありませんでした.
ざっと確認した所,このような問題がありました.
これらを踏まえて,fs_moodleは私が作ってきた日本語ファイル名対応よりも優秀だと感じましたので,学内のMoodle利用者の方々にも試用していただこうと考えています.
現在Moodle1.8.3+ 07/10/24版をベースに開発中の学内のシステムをfs_moodle化しました.これを学内の方々に試用していただきフィードバックから,問題の原因究明や,他の問題が無いか検証したいと思います.
新たな問題や問題の解決策を見つけた場合はご報告させていただきます.
#ちなみにfs_converterのライセンスはGPLでしょうか.
まずクライアント側で作成するZIPファイル書庫内のファイル名/フォルダ名ですが,
- Macで作成(パターン1,2) :UTF-8
- 日本語Windowsで作成(パターン3,4) :シフトJIS
{
$str = mb_convert_encoding($str, 'UTF-8', $encoding);
return $str;
あ,ちなみにパターン1,2においてMacで作成してアップロードしたZIPファイルをWindowsXpでダウンロードしても正しく展開できない(ファイル名が化ける)のはPC上のZIP/UNZIPプログラムの仕様上の問題ですね.ヘッダーの文字コードの種別の違いをクライアントの展開ソフトウェアが吸収できないと無理です.
zip関係のソースコードにはあまり手を入れない方針で進めています.したがいまして,fs_moodle上でzip書庫を作成する際の文字コードはファイルシステムの文字コードです.サーバが日本語WindowsならばシフトJISで圧縮します.fs_moodleのファイルシステムの文字コードをシフトJIS以外(UTF-8など)に設定している場合,fs_moodleでZIP書庫作成の際に,シフトJISでZIP書庫作成,という選択肢が増えているはずです.そのままMoodle上でZIP書庫を作成すると日本語Windowsでは展開できませんが,ファイル名を強制的にシフトJISに変換することで,日本語Windows上で正常に展開できるようにする仕組みです.
でも,考えてみたら,これはクライアントが日本語WindowsのPCであることを前提としている仕組みですね.サーバが日本語Windowsの場合はUTF-8での書庫作成ができないということを意味しますので,ユーザにUTF-8か,シフトJISかを選べるようにするべきでした.
当方,Macの環境がありませんので,Macで作成したZIPファイルでのデバッグが行えません.実験に使用したZIPファイルをここにアップして頂けないでしょうか? それを用いてデバッグおよび機能の変更を行います.
(ただ,迂闊に手を入れすぎると,バックアップ/リストア機能に支障が出るので慎重に進めたいと思います)
fs_moodleは基本的にGPLです.と私が言ってしまって良いのか,自信がありません.MoodleがGPLならばfs_moodleもGPLです.ソースコードに手を入れたところは全てオリジナルをコメントアウトして残してありますし,どこをどのように修正しているのか,は,Wikiに記録してあります.配布しているパッケージをfs_moodleと言うのも少しおかしいかな?と思いますし,fs_converter.phpとWikiのデータがfs_moodleなのでしょうねぇ.
奥村先生も仰っているように日本のMoodlerで行った日本語対応の知恵を集約するには実証するプラットフォームがいくつか必要であり,その一つがfs_moodleであると思っています.元々の動機が日本語Windows上でMoodleを使えるようにしよう,でしたが,プラットフォームに依存しない修正も多数,取り込まれてきました.
http://www.suzuka-ct.ac.jp/mech/moodle/mod/wiki/view.php?id=320&page=fs_moodle%E4%BF%AE%E6%AD%A3%E7%AE%87%E6%89%80%E4%B8%80%E8%A6%A7
このWikiがその資産なのですが,
- 日本語WindowsなどのUTF-8に非対応なOSへの対応
- IEが日本語URLに対してシフトJISしか未対応
- 年月日や氏名の並びといったローカライズの軽微な改善
- mb_string系関数を使用しないために発生する致命的な問題
しかし...修正箇所が多くなり過ぎました.Moodle1.8からMoodle1.9に無事にアップグレード可能なのでしょうか.いまから戦々恐々です
しかし,WindowsでアーカイブしたものでもStuffIt Expanderで今まで普通に展開できていましたので,ファイル名がShift JISでもちゃんと直してくれるようです。ということで,Shift JISにして束ねるということでWindowsもMacも大丈夫だと思います。
三重大学版Moodle(1.6ベース)でも最近のは課題の提出物全部とかフォーラムのディスカッションの添付ファイル全部とかをZipしてダウンロードする機能がついています(業者さんに作ってもらいました)。これも中身はShift JISファイル名です。
ありがとうございます.
確かに,archive.zipを日本語Windows上で動作するアーカイブユーティリティのExpLzhを使用して展開したところ,正しく「ほげ.txt」と「げほ.txt」が得られました.
五月女さんの書き込みをもう一度,読み直してみると,ダウンロードしたzipファイルの中身が悪くて展開できなかった,のではなく,zipファイル自体のファイル名がWindowsXP+IE6では化けてしまったために展開できなかったと書いてありました.私の読み間違いです!
考えてみたら当然ですね.シフトJISでエンコードされたZIPファイルが広く世の中に蔓延している中,Macのアーカイバで展開できないとは思えません.逆はあり得ますが!(シフトJISに統一,は了解です).
そして...いつの間にか日本語ファイル名のファイルをIEでダウンロードすると文字化けする問題が復活していました.根本的な部分ですね.パッチを当てる作業をいつかの時点で失敗したのかも知れません.調査します.
原因が分かりました.本家のMoodle1.8.3+のコードが改善されています.
つい先日のMoodle1.8.3+のCHANGESにそれらしい修正がありました.
差分を取ったときにも「おや?」と思ったのですが,そのまま忘れていました.
以前,水野さんが報告していた,IEでファイル名が化ける問題の対策,ヘッダーの$filenameをurlencode()すれば保存されるファイル名がマルチバイト環境下で化けない,という対策が本家に採用されたようです.
http://moodle.org/mod/forum/discuss.php?d=72567
lib/filelib.phpのfunction send_file()に,
if (check_browser_version('MSIE')) {
当方の環境では,奥村先生が以前に示されたコードに基づいた以下のコードを用いていました(file.php).
$ua = $_SERVER['HTTP_USER_AGENT'];
if (strstr($ua, "MSIE") && !strstr($ua, 'Opera')) {
// $filename = urlencode($filename); // 上記と置き換え可能
$filename = str_replace('#', '%23', $filename);
send_file($pathname, $filename, $lifetime, $CFG->filteruploadedfiles, false, $forcedownload);
つまりファイル名をシフトJISに変換した後に,urlencode()も行われていた,ということですね.
もし水野さんのurlencode()部分が有効だった場合は,urlencode()のurlencode()になってしまう,と.
file.phpでのIE対策のファイル名のコード変換の処理を行わないようにコメントアウトすると,いままでどおりにIEでも日本語ファイル名のファイルをダウンロードできるようになりました.
なお,urlencode()でファイル名を送信すると,半角空白が+(つまり”ほげ ほげ.zip"は"ほげ+ほげ.zip"になる)になってしまいます.
@header('Content-Disposition: attachment; filename="'.$filename.'"');
@header('Content-Disposition: inline; filename="'.$filename.'"');
filelib.phpのurlencode()をrawurlencode()に変更すれば,(当方の環境では)ファイル名中に半角空白を含んでも,+に変換されずに正しいファイル名で保存されます.
シフトJISに変換するのが良いのか,rawurlencode()が良いのか,判断し辛いですね.
なにはともあれ,上記file.phpの紫色の行のコードは不要になった,と考えて良いでしょう.
あとは新しく追加されたfilelib.php中のurlencode()をrawurlencode()にするか,mb_convert_encoding($filename, "CP932", "UTF-8")にするか,だけですね.
$ua = $_SERVER['HTTP_USER_AGENT'];
if (strstr($ua, "MSIE") && !strstr($ua, 'Opera')) {
$filename = mb_convert_encoding($filename, "SJIS-WIN", "UTF-8");
$filename = str_replace('#', '%23', $filename);
} elseif (strstr($ua, "Safari")) {
$filename = "";
}
になっているみたいです。SJIS-WIN(CP932)にするのは日本の国内事情にしか合わないので,rawurlencodeすればどこの国でもうまくいくのであればそちらのほうがよさそうですね。ただ,長いパス名になってしまって途中で切れるという問題はなかったでしょうか。
Opera利用者はMSIEを詐称することが多いということを聞いたので if (strstr($ua, "MSIE") && !strstr($ua, 'Opera')) としたのですが,本家の修正ではそのあたりがなくなってしまっていますね。あと,ファイル名に # が含まれる場合の問題もありましたね。
”長い長いファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の.xls”(全角50文字+半角4文字)をダウンロードしてみました.テスト用の長い名前のファイルは,常識的な長さのファイル名のExcelファイルをアップロードし,Moodle上でリネームして作成しました.
$filename = rawurlencode($filename)の場合,ダウンロードされたファイルのファイル名は,「8Dの長い長いファイル名の長い長いファイル名の.xls」です.頭の8Dは%8Dの一部? 何はともあれ全角21文字+ゴミと拡張子(半角4文字)が限界のようです.
それに対して,$filename = mb_convert_encoding($filename, "CP932", "UTF-8")でシフトJISに変換した場合は,「長い長いファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の.xls」,正しく全角50文字+半角4文字で保存できました.
60文字もOKです.では100文字は?
Moodle上でのファイルのリネームには成功しました.
ダウンロードしたところ,さすがにここまでいくと無理があったようで,「ファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の長い長いファイル名の.xls」96文字+4文字,4文字ほど頭が欠けているようです.
ちなみに100文字+4文字のファイルは,アップロードに関しては問題ないようです.中途半端ですねぇ.
MS-DOS世代の私は半角8文字+拡張子3文字を潔しとして長らく生きてきたのですが,元・商社のデキるOLのうちの妻が作成する”名は体を十二分に表す”長い長いファイル名に思わず「ヤメテくれぇ」と言いかけたのですが,「もう制限に囚われる必要はないのだ」と思うと急に気が軽くなったのを良く覚えています.「なんでだめなの?」とキョトンとされて,ハタっと.
さすがに100文字は画面から溢れるので非常識ですが,rawurlencode()の20文字程度というのは短いですね.シフトJISにします.
ところでお恥ずかしい話ですが,#を%23に置換する理由は何でしたか?
いま試してみたところ,確かにシフトJISで送信する際に#は_に置換されていますので,%23に置き換える必要があることは確認しました.誰が#を_に置き換えているのかな?
あと,思い出したときに書いておきますが,うちでなぜCP932としないでSJIS-WINとしたかというと, PHP: Multibyte String Functions - Manual で
Additional note: For the CP932 codemap, use SJIS-WIN instead.
と書いてあるんです。どういう意味だかわからないけれど,素直に従いました。
if (check_browser_version('MSIE')) {
他にも色々とテクニックが用いられているようですが,いまひとつ内容が理解できません.きっと何かノウハウなのでしょう...
対応が遅くなりましたが,file.phpとlib/filelib.phpの該当箇所を変更したところ,
IE6にて文字化けすることなく,ファイルのダウンロードが出来る事を確認しました.
ありがとうございます.
MacOSXよりアップロードした,機種依存文字を含むファイル名でも正常にダウンロードできました.(丸囲み数字やローマ数字)
文字コードについては,文字コード変換よりはurlencodeに賛成なのですが,
urlencodeですとどうしても送信文が長くなり,POSTやGETの長さ制限に引っかかってしまうんですよね
何がベスト(もしくはベター)な解決策なのか悩んでしまいます.
そうですね.シフトJISに変換するという日本ローカルな対応はrawurlencode()した文字の長さによって,特例として入れるのが良いと思います.
その辺の調査と改善を行うのに併せて,もう一つ,実は気になっていることがあります.
まだ調査が中途半端な状態なのですが,send_file()関数はいま気にしている箇所(file.phpから呼ばれる箇所)以外にも,他の関数からも呼ばれているような気がします.マルチバイトへの対応として,urlencode()をsend_file()内に組み込んだ本家の改善は,この問題にも対応しようという現われなのではないでしょうか.
grepでsend_fileをコールしている箇所を調べたところ,$filenameを指定しないでsend_file()を呼んでいる箇所も多く,その場合は問題ないのかも知れませんが,いくつか$filenameを引数として渡している箇所もあるようです.だとすると,これらのIE対応は本家同様にsend_file()内に組み込むべきなのか,とも思います.
file.phpから呼ばれる箇所以外は,ANK文字列のファイル名以外はあり得ない,という性質を持つならば現状で構わないと思うので,いったい,どのようなファイル名を渡される可能性があるのかを見極めながら対応策を考えています.
#気にしすぎ? send_file()内に移動させてしまいましょうか.
また,send_file()内を変更するのは良い案だと思います.
WindowsXPのフルパスは意外と短かった気がしてググった所,
ファイルシステムによるみたいですが,255バイトのようです.
http://q.hatena.ne.jp/1169126961
Moodle1.8.3+用の改造です.
file.php中の
if (strstr($ua, "MSIE") && !strstr($ua, 'Opera')) {
$filename = str_replace('#', '%23', $filename);
lib/filelib.php, send_file(): 347行近辺.最新のMoodle1.8.3+では,以下のようなコードが追加されています.
if (check_browser_version('MSIE')) {
この箇所を以下のように修正しました.
if (check_browser_version('MSIE')) {
if (strlen(rawurlencode($filename)) > 21 * 3 * 3) {
$filename = str_replace('#', '%23', $filename);
check_browser_version()関数をオリジナル通りに利用してみました.
21文字×3でUTF-8,さらに×3はURLエンコード分です.取り敢えず色々と実験してみましたが,大体この程度で良さそうです.
urlencode()ではなく,rawurlencode()を使用しているのは,ファイル名に半角空白を含む場合です.
オリジナルのMoodleではファイル名に半角空白を許していないので,urlencode()でも問題ありませんが,当方の環境では半角空白も許しているのでrawurlencode()を使用しました.関数としての機能の違いは半角空白を+に変換するか%20(でしたっけ?)に変換するのかの違いだけだと思いますので,rawurlencode()でも皆さんの環境で問題は無いと思います.
send_file()関数の頭のところで,
実験した感じでは,どちらでもあまり挙動に違いがありませんでしたので,オリジナルに近い改造を選択しました.
近日中に,fs_moodleのパッケージも更新します.(今週末?)
send_file()内に移動させたファイル名のエンコードをブラウザの種別に合せて変換する機能を関数にしてみてはどうかと考えて,いまテストしています.
// ブラウザに合わせてダウンロードファイル名のフォーマットを変更する
function convert_download_filename_encoding($filename) {
if (check_browser_version('MSIE')) {
if (strlen(rawurlencode($filename)) > 21 * 3 * 3) {
$filename = mb_convert_encoding($filename, "SJIS-WIN", "UTF-8");
$filename = str_replace('#', '%23', $filename);
} else {
$filename = rawurlencode($filename);
}
} else if (check_browser_version('Safari')) {
$filename = "";
}
return $filename;
}
send_file()以外にも何箇所か(具体的にはWikiのエクスポート機能)で,ダウンロードしたファイル名がIEだと文字化けする箇所があります.メンテナンスもやり易い気がします.
さて,ところで.ブラウザがSafariの場合は$filename = ""としていますが,これはこれで良いのでしょうか??? 実は前々から少し気になっていました.send_file()で,$pathが指定されている場合は大丈夫,ということだと,上記関数をあちらこちらで使用するのに問題があります.
そもそも(Wikiのエクスポートのように)send_file()を使わないのがおかしい,となれば,そのように考えますが,もしSafariの場合も$filename=""にしなくても問題が無いのならば安心です(つまりFirefox同様に生のUTF-8をHeaderに渡して構わない).
奥村先生のWebページに理由が書いてありました.
http://oku.edu.mie-u.ac.jp/~okumura/php/filename.php
なるほど.Safariにもこのような悩みがあったのですね.
関数としては,Safariの場合は空文字を返すということとし,関数を利用した側でもし戻り値が空文字ではいけない(画面表示などに再利用する,というのもSJIS-WINやrawurlencode()された文字を返す可能性のある関数の性質上,変ですが)場合は自分で判断しなさい,とコメントを付しましょう,か.