というわけでファイル所有者の件で、少しまとめておく。

php から普通にファイルをつくると所有者は apache になるようだ。

ファイルをつくった時 chown() すればいいのかなと思い php マニュアルをみたら:

>スーパーユーザのみがファイルの所有者を変更できます。

と書いてあるので、レンタルサーバーなどで運用している場合使えない。しかし apache 所有だと FTP クライアントから消したりできんので非常にうっとおしいのも事実だ。

ぐぐってみると、「 CGI 版 php を使う」「php の ftp関数を使う」という逃げ方があるという話だけ見つかった。(意外にも、同じ問題で困っている人の質問は見つかったが、ずばり解決な情報は見つからなかった。)

ここで、この問題がなぜ起こるのかを考えてみた。要は「 php で作ったファイルやディレクトリが ftpクライアントからいじれない。」というわけだ。その理由は「 php の fopen() で新規にファイルをつくるとき、その所有者を指定して開くことができない。」ことと、「作成したファイルの所有者を変更する関数 chown() はスーパーユーザー(簡単に言うとルート権限をもつユーザー。)しか使用不可能という仕様。」だからだ。

一言で言うと、いきなりでなんだが「八方塞がり」だ。(笑)

だが、もし php から作るときにも ftp 経由で普段のユーザーとしてログインし「ファイルをつくる」ことができれば、問題はなさそうだ。

もしかしたら php の ftp関数を使うことで ftp 転送したときと同じ所有者にできるかも知れない。(ファイル転送ではなく、新規作成ができなければ実現できないが…普通 FTP といえばファイルを get/put するための仕組みだろうから、もしかしたら、いきなりでなんだが新規作成などということは無理かも知れない。(^^;)

また、画像ファイルなどをアップロードする XML-RPC API newMediaObject() の仕様として「転送先ディレクトリが存在しなければその場で作る。」というのがある。 php の ftp関数でディレクトリが新規に作れるかどうかは知らない。

というわけで、 FTP 転送時と同じ所有者でファイルとディレクトリを作るようにしたいところだが、とりあえずは apache 所有者で作られても ftp で手でファイルを消したりしようとしない限り普通に使えるし、よい解決方法がみつかるまではこれでいいかと。

しかし…「ファイルを1つつくる」などという基本的なことでけっこう頭を抱えなければならないんですなぁ。(苦笑)

php のマニュアルで ftp 関数を調べてみた。

>ftp_mkdir -- ディレクトリを作成する

ディレクトリの作成はできそうだ。

>ftp_fput --  オープン中のファイルをFTPサーバーにアップロードする

ファイルの新規作成については、こんなのがあった。ファイルポインタで指定して、ファイルの終端までをアップロードするそうだ。

この関数は、既存のファイルを開いて取得したファイルストリームを受け取って、ファイルストリームの末尾までを一気にリモートにアップロードする仕様らしい。

XML-RPC API 側でファイルを作成するときに、メモリストリームをつくり、受け取った記事内容をストリームから一定量ずつ流し込むなり fwrite 系の一定量ずつメモリブロックを読み書きするなりできるような関数があれば、今回やりたいことを実現できるのだが、上の関数では、一気に最後まで書き込んでファイルをつくる仕様なので無理だ。 php にはメモリストリームをあつかうためのクラスもないようだ。

困った…。

  1. FTP 転送自体を php でフルスクラッチする。
  2. php 以外のサーバーサイドスクリプトをつかう。
  3. 一旦 apache 所有のファイルを新規作成し、しかる後に、そのファイルから ftp_fput する。

1. は大変すぎだしプラットフォームによっては動かないようなものしかつくれそうにない。

2. は rn_xmlrpc.php の API との連携が大変。

3. なら実現できるだろうが…。無駄が多くてバカバカしいんだがなぁ。(いったん apache 所有でつくって、put して消すので、処理中のディスクサイズがファイルサイズの2倍必要になる。記事ならそれほど問題にならないだろうし newMediaObject で転送するファイルも過去の実測でいうと 1.5MB 程度までしか転送できなかったので、運用上いいっちゅやいいんだが…。(^^;)

理想的には、ファイルの転送をシミュレートするような ftp_fwrite , ftp_fread, ftp_fseek みたいなものがあればそれがズバリなのだが…

[コメントの受付は終了しています ]
1: (12/26 06:57)
似たような問題で困ったことがあります。
その時は新規作成するファイルが有限だったので、対象となるファイルを事前にFTPでアップロードしておき、CGIではそのファイルを書き換えるようにしていました。
有限でない場合で、FTPでファイルをアップロードできるのであれば、サーバー上にダミーファイルを置いておき、そのダミーファイルを開いてそのファイルハンドルを渡してFTPで上げると言うのはどうでしょうか?
試してはいませんが、phpのマニュアルを見た限りでは出来そうな気がします。
2: 冬星 (12/26 14:41)
こんにちは。吉里吉里の方ではお世話になってます。
おお、実現できそうですか?
おっしゃっている「ダミーファイルのファイルハンドルを渡して」というのは ftp_fput() にですよね。
soruce 側の fp に、ダミーファイルを開いてその fp を渡すということでしょうか。
そのあと、メモリ内に string としてもっている記事本文の情報を書き込む必要がありますがその部分の方法がわからんです。(^-^;
3: (12/26 17:21)
こんにちは、こちらこそお世話になってます。

次のような感じでどうですか?
私のところで試したところ、うまく行きました。
書き込み後は、またFTPでつないでパーミッション変えたほうがいいかもしれません。
chmodが使えるのなら、FTP使わずに出来るのですが、禁止されているかと。
ただ、この方法だとFTPのパスワードが入ってしまうので、その辺りはちょっと注意した方が良さそうですね。

ダミーファイルに書き込んでから、それをコピーすると言う手もありかもしれません。
その場合はパーミッションをいじらなくてすみそうです。
4: (12/26 17:21)
<?php
$path = "/your/site/full/path/"; // ダミーを置いておくディレクトリ、今回は作りたいファイルもここに置く
$templatefile = "template.txt"; // 初めに上げておくダミーファイル名
$writefile = "target.txt"; // 新たに作りたいファイル名

$FTP_HOST ="ftp.yourhost.co.jp";
$FTP_USER ="yourname";
$FTP_PW ="yourpw";
$FTP_ROOT_DIR="/";
$FTP_DIR = "targetdir/";
$is_copy_success = false;
5: (12/26 17:21)
$conn_id = ftp_connect($FTP_HOST);
if( ftp_login($conn_id, $FTP_USER, $FTP_PW) ){
  print "success FTP login<br>\n";
  ftp_pwd($conn_id);
  ftp_chdir($conn_id,$FTP_DIR);
  $filename = $path . $templatefile;
  if( $fp = fopen($filename, 'rb') ) {
    if( ftp_fput( $conn_id, $writefile, $fp, FTP_ASCII ) ) {
      print "success copy file.<br>\n";
      $chmod_cmd="CHMOD 0666 ".$writefile; // ftp_chmodは通らなかったのでこれで
      if( ftp_site($conn_id, $chmod_cmd) ) {
        print "success chmod.<br>\n";
        $is_copy_success = true;
      }
    }
    fclose($fp);
  }
  ftp_quit($conn_id);
}
6: (12/26 17:21)
$write_data = "書き込みたい内容が入った変数";
if( $is_copy_success ) {
  $filename = $path . $writefile;
  if( file_exists($filename) ) {
    if( $handle = fopen($filename, 'wb') ) {
      if( fwrite($handle, $write_data ) ) {
        print "Success write file.<br>\n";
      }
      fclose($handle);
    }
  }
}
?>
7: 冬星 (12/26 20:18)
詳しい解説ありがとうございます。>楓さん
理解しました。
所望の所有者で作っておいた空ファイルの複製をFTPでつくり、開いて書き込むことで所有権を維持、ですね。
うまいやり方ですね。ちと取り入れてみます。(^^
8: 冬星 (12/26 20:54)
FTP アカウントでファイル/ディレクトリ作成することもできるように修正してみました。
うまくいきましたよ~。>楓さん。
9: (12/28 16:29)
こんにちは。
うまく行きましたかー
それは良かったです。
この記事のリンク元 | 4 | 1 |

memo: xhtml 2005-11-19 (土) 03:34:00+09:00

ソフトウェア

Webページを記述するためによく使われるHTMLを、XMLに適合するよう定義し直したマークアップ言語。W3Cが仕様策定。

HTMLはXMLとは一部整合性を欠く言語仕様となっているが、両者の違いはある程度吸収できる範囲のものであるため、従来のwwwブラウザでも問題なく見られ、かつXMLに準拠した文書を作成する言語仕様としてXHTMLが作成された。

最初のW3C勧告となったXHTML 1.0はHTML 4.01が元。HTML 4.01に対応したWebブラウザでほぼ完全な形でページを見られる。

現在の最新版はXHTML 1.1で、文書見栄えを指定するタグが廃止(見栄えの記述は全てCSSで行なう)など、文書構造の記述に特化した言語へと変化しつつある状況。

XHTMLの各バージョンに共通したHTMLとの違い:

タグ名がすべて小文字に統一。
XMLベースの他の言語(MathMLやSVGなどが想定されている)による記述を埋め込むことができる。
終了タグをもたず単独で使用される
などのタグを
ないし
と書く。
e-wordsのXHTMLの項から抜粋。


The Web Standards Project の記事 MSIE7 Will Not Support application/xml+xhtml MIME Type によると:

IE7 の開発チームは、IE7 では xhtml への対応は実装しないということらしい。

来るべき未来の IE7 でも xhtml 形式での表示にきちんと対応できないとなると、投稿クライアントとしてもきちんと対応することはできない。(なにしろ、最終的にそれを表示するブラウザが対応していないんだからね。)

現状でできることといえばエディタに IE の WebBrowser コンポーネントを使用してやって、表示の「出来具合」を合わせて「IE自身の仕様です」とする。これぐらいか。

あるいは、Firefox あたりが編集モードももったブラウザコントロールを配布してくれればありがたいんだが、ないんだろうか。htmlメールも作れるメールクライアントへの組み込みなど需要は高いと思うんだが、知っている限りは、スタンドアローンな WYSIWYG 編集アプリケーションとして Nvu があるぐらいか。

というかよく知らないんだが、Firefox や Mozilla は xhtml のどのバージョンにどの程度対応済みなんだろう?



Firefox というより Mozilla のブラウザコントロールがあるようだ。

それのActive-X ラッパーがあるそうなので Mozilla ActiveX Project からMozillaControlの1.7.7 というものを手に入れてインストールしてみたが、開発環境にコンポーネントとして認識されなかった。あらまぁ。


BlogWrite と mt_convert_breaks 2005-08-27 (土) 00:00:00+09:00

ソフトウェア

しばらく静かといいつつナニなんだが、一件やっておかないといけなかった修正をした。

metaWeblog.newPost, editPost で mt_convert_breaks が 1/convert_breaks だった場合に、改行コードを p タグの組み合わせに変換するようにした。

それで気づいたが BlogWrite で本文を入力し自動改行にチェックを入れてみたところ色々と不思議な動作をする。

  1. 本文を手入力して、新規投稿のときチェックを入れて送信→「投稿&公開」ボタンを押した瞬間にチェックが自動で外れ、 mt_convert_breaks == '0' で送られる。
  2. 本文をテキストエディタからペーストして新規投稿として送信→ mt_convert_breaks == '1' で送られるが、 <br /> が付加された本文のままで送信するので、結果的に br タグの上に更に p タグが付いてしまう。
  3. 編集して再投稿するときチェックを入れて送信→ mt_convert_breaks == '1' で送られるが、 <p></p> が付加された本文のままで送信するので、結果的に p タグが重ねがけされてしまう。

1.に関しては、かならず自動改行OFFでしか送られないようにブロックしているようだ。本文入力中に既に p タグが入力されているから自動改行する必要なしとの判断をしているのだと思う。

2.に関しては、テキストエディタから本文に貼り付けたとき、連続して何か書かれている行末には <br /> が自動挿入され、段落間は p タグが自動挿入される(賢い!)のだが、その状態で自動改行オンにして新規投稿すると、こちらはなぜか強制OFFしないでそのまま送ってしまうので、結果的に改行が二重に効いてしまい間延びした文書になってしまう。既に改行のための処理をしてあるのだから、1.と仕様を合わせて自動改行をOFFにすべきではないか?

3.に関しては、既に投稿済みの文書なので、改行の処理は済んでいると思われるのに、自動改行ONのままで送信するので確実に二重に改行処理がほどこされてしまう。

検証して思ったが BlogWrite のように WYSIWYG 処理の都合上、編集画面上改行されているところは改行用のタグが挿入されているツールの場合、1.から3.いずれの場合も、自動改行は強制的にOFFのはずだ。「自動改行=改行コードを改行に相当するタグに置き換える」処理の意味が成立しないからだ。

もし自動改行ONのモードをもたせるとしたら、手入力で改行した位置と、エディタなどから貼り付けたテキストの改行の位置を内部で保持しておき、送信時にそれらを改行コードとして送信する必要がある。ただそれだと、 html とかを貼り付けられた場合には、タグを解析してどこが改行や段落なのかを把握する必要が生じる。解析して改行を管理するか、常に自動改行OFFか、どちらかに統一が必要な気がする。

[コメントの受付は終了しています ]
この記事のリンク元 | 1 | 1 | 1 |

キーワード: BlogWrite mt_convert_breaks


文字列を1文字ずつみて ACSIIコードを16進表示するスクリプトを PHP で書いた。

side bar に「WEPキー作成補助」として追加した。

単純なものだが WEP キーを無線ルータに設定するとき重宝しそうだ。客先で時間がおしてくると、文字列→16進を紙で照合するのも大変だし間違いが生じそうだからだ。

核の部分はこれだけ。

for ($i = 0; $i < strlen($str); $i++) {
print strtolower(bin2hex($str[$i]));//または strtoupper(...)。
}

それにしても、製作の過程で検算のために ASCII コード表など拝見したが、なつかしい。自分がマイコンに触れた頃は、グラフィック画面などなく、文字コードといえばコレのJIS拡張版(半角カナ等付き)もう少し正確にいうとメーカー独自のセミグラフィックコード(≒絵文字)の入ったコード表が唯一全てだった。今はややこしい…。