【PHP】クッキーを書き込んだ直後のリダイレクト

setCookieなどでクッキーを書き込んだ直後に、header関数でリダイレクトすると、場合によってクッキーが消えることがあります。(ブラウザー依存みたいです)

※セッション値のセットも同じような現象が発生する可能性があります。

→ クッキーを利用する際に、headerより、ページを表示させてからrefreshやjavascriptで飛ばすほうが安全です。

【PHP】get_headersで「https」のヘッダーを取得する時のエラーと解決策

PHPのバージョンは5.2.9です。(環境:Windows + Apache)
get_headers関数に「https」を渡したらエラーになりました:

  $ary_headers = get_headers("https://example.com", 0);
  print_r($ary_headers);

でアクセスをしにいくと、下記のエラーが出ました:

Warning: get_headers() [function.get-headers]: This function may only be used against URLs. in XXXXXXXXXXXXXXX

→ 解決策:
実は、php.iniの中のphp_openssl.dllがコメントアウトになっているだけです。
php_openssl.dllを有効にしてApacheを再起動すれば、エラーが消えます。

;extension=php_openssl.dll
→
extension=php_openssl.dll

※phpinfo()で確認できます:

(1)php_openssl.dllが無効になっている場合、
【Registered PHP Streams】php, file, data, http, ftp, compress.zlib, zip
【Registered Stream Socket Transports】tcp, udp

(2)php_openssl.dllが有効になっている場合、
【Registered PHP Streams】php, file, data, http, ftp, compress.zlib, https, ftps, zip
【Registered Stream Socket Transports】tcp, udp, ssl, sslv3, sslv2, tls

みたいな感じです。

Webサーバー構築メモ — Cent OS 5.7

サーバー構築を構築しています。経験があまりないので、メモとして今回の問題点と解決策をまとめます。

【環境】
Cent OS 5.7
Apache 2.2.3
PHP 5.2.10

【問題1】
.htaccessでmod_rewriteを使ってリダイレクトをしようとしても動きませんでした。
エラーログ(/var/log/httpd/error_log)を確認すると、下記のエラーがありました:

Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden: /XXX/XXX/XXX

→ 解決策: /etc/httpd/conf/httpd.confの<Directory>セクションの設定をします。
(1)<Directory>セクションのOptionにFollowSymLinksをつけなければなりません。
そうしないと、上記のエラーが出てきます。
(2)<Directory>セクションのAllowOverrideをNoneに設定してはいけません。
Noneに設定してしまうと、.htaccessでの上書きが出来なくなります。AllかFileInfoに設定します。
↓↓大体は下記の感じです↓↓

<Directory "/XXX/XXX/XXX/">
  Options FollowSymLinks
  AllowOverride All
  Order allow,deny
  Allow from all
</Directory>

詳細は下記サイトを参照してください。
Apache HTTP サーバ

【問題2】
複数ドメインのDocumentRootの設定
例えば、httpd.confのDocumentRootは”/var/www/html”だとします。
そうすると、直接ipアドレスでアクセスしてくると、/var/www/htmlがルートになります。
→ ただ、事前に取得しておいたドメインexample.comでアクセスすると、/var/www/htmlではなく、/var/www/htmlの下の「aaa」というディレクトリーを見るように設定したいです。
つまり、「http://www.example.com」 ⇒ 「/var/www/html/aaa」にしたいです。
→ 解決策: /etc/httpd/conf/httpd.confの<VirtualName>セクションの設定をします。
例えば、一番簡単な設定は下記のようです↓↓

NameVirtualHost *:80
<VirtualHost *:80>
  DocumentRoot /var/www/html/aaa
  ServerName www.example.com
</VirtualHost>

もしhttps(SSL)にも対応したい場合には、443番ポートなので、下記のも必要です↓↓

NameVirtualHost *:443
<VirtualHost *:443>
  DocumentRoot /var/www/html/aaa
  ServerName www.example.com:443
</VirtualHost>

他にもいろいろ設定できますので(CustomLogやErrorLogやServerAdminなど)、下記サイトを参照してください。
Apache バーチャルホスト説明書 – Apache HTTP サーバ
※注1:CustomLogを設定する時、ログのフォーマット「LogFormat」の設定も必要です。
例えば:

LogFormat "%h %v %l %u %t \"%r\" %>s %b" commonvhost
NameVirtualHost *:80
<VirtualHost *:80>
  DocumentRoot /var/www/html/aaa
  ServerName www.example.com
  CustomLog /etc/httpd/logs/example.com-access_log commonvhost
</VirtualHost>

LogFormatの詳細は、下記サイトを参照して下さい。
ログファイル – Apache HTTP サーバ

【問題3】
PHPのDOMのインストール
今回の件はDOMが必要ですが、インストールされていません。
↓↓下記のようにyumで簡単にインストールできました↓↓

yum install php-xml

Cent OS 5.7でのPHPバージョンアップ:5.1 → 5.2

基本的に
HowTos/PHP 5.1 To 5.2 – CentOS Wiki
のままでOKでした。

 

簡単にまとめてみると:
(1)現在インストールされた物の確認:
# rpm -qa | grep php

(2)/etc/yum.repos.d/の下に、下記内容で「CentOS-Testing.repo」という新しいリポジトリを追加します↓↓

  [c5-testing]
  name=CentOS-5 Testing
  baseurl=http://dev.centos.org/centos/$releasever/testing/$basearch/
  enabled=1
  gpgcheck=1
  gpgkey=http://dev.centos.org/centos/RPM-GPG-KEY-CentOS-testing
  includepkgs=php*

(3)アップデート
# yum update

(4)念のためhttpdを再起動
# service httpd restart

 

という感じです。

デフォルトゲートウェイ「0.0.0.0」 — Windows7 — 急にインターネットに繋がらなくなった

今朝パソコン(OSがWindows7)が立ち上げたら、インターネットに接続できない状態になった現象が発生しました。前日設定などは一切やっていませんでした。
ipconfigで確認したら、

  IPv4 アドレス . . . . . . . . . . : 192.168.11.2
  サブネット マスク . . . . . . . . : 255.255.255.0
  デフォルト ゲートウェイ . . . . . : 0.0.0.0
                                      192.168.11.1

謎の「0.0.0.0」が現れました。

下記の記事に解決策が載っています:
俺の覚書 Windows7が急にネットワークに繋がらなくなった

→ 簡単にまとめますと、コマンドプロンプトで、

  (1)ネットワーク宛先0.0.0.0、ネットマスク0.0.0.0のテーブルを削除:
route delete 0.0.0.0 mask 0.0.0.0

  (2)ネットワーク宛先0.0.0.0、ネットマスク0.0.0.0、ゲートウェイ192.168.11.1のテーブルを追加
route add 0.0.0.0 mask 0.0.0.0 192.168.11.1

以上で、問題を解決しました。
※具体的な原理などについて、上記の記事「俺の覚書 Windows7が急にネットワークに繋がらなくなった」を参照してください。

javascrpitの正規表現による文字列置換「String.replace」について

まず、簡単な例を見ていましょう:

例題1:

「#A」「#B」「#C」のみ、頭の「#」を消します。
(例えば、”#AA#BB#CC#D” → “AABBCC#D”)

それは簡単です。

str = "#AA#BB#CC#D";
str = str.replace(/#([ABC])/g, "$1");

でOKです。

ただ、マッチした結果に対してさらに複雑な処理を行いたい場合にはどうしますか。

例題2

「#A」「#B」「#C」のみ、頭の「#」を消して、小文字に変換します。
(例えば、”#AA#BB#CC#D” → “aAbBcC#D”)

たぶん下記の方法を考えた方がいらっしゃるだろうと思いますが、実はNGです。

// × NG
str = "#AA#BB#CC#D";
str = str.replace(/#([ABC])/g, "$1".toLowerCase());

“$1″という文字列オブジェクトにtoLowerCase()を使ってしまったのです。

↓↓↓↓↓

では、下記のやり方はどうですか。

// △ FirefoxやGoogle ChromeだとOK
str = "#AA#BB#CC#D";
str = str.replace(/#([ABC])/g,
  function() {
    return RegExp.$1.toLowerCase();
  }
);

replaceの中で無名関数を使うという方法です。
テストした結果、うまく行けたブラウザーもあれば(Firefox、Google Chromeなど)、行けなかったブラウザーもあります(IEなど)。

↓↓↓↓↓

Electronic Genome
↑というブログを参考したら、下記のやり方だとIEでも動きました:

// 〇 OK
str = "#AA#BB#CC#D";
str = str.replace(/#([ABC])/g,
  function(whole, p1) {
    return p1.toLowerCase();
  }
);

つまり、replaceの中の無名関数に、引数を渡しました。

→ やっと、問題を解決しました!

※wholeやp1など、引数の具体的な意味について、
Electronic Genome – JavascriptのString.replaceに無名関数を渡して複雑な置換
↑を参照してください。

画像の一部を表示する方法

簡単ですが、一応まとめましょう。

元の画像はこちら↓

中央の笑顔のみ表示したい場合は、外側に広さと高さが決まった親ボックスに「overflow:hidden;」を適用し、インナーを1つ挟めばOKですね。

具体的には:

できました(^^)

ソースは下記のようになります:

CSSの部分:
div#imgContainer {
  position: relative;
  width: 67px;
  height: 67px;
  overflow: hidden;
}
div#imgContainer #imgInner {
  position: relative;
  width: 128px;
  height: 128px;
  left: -30px;
  top: -25px;
}
div#imgContainer #imgInner img {
  position: relative;
  width: 100%;
}

HTMLの部分:
<div id="imgContainer">
  <div id="imgInner">
    <img src="画像のパス">
  </div>
</div>

ADOでの時間切れについて

DB環境:Microsoft SQL Server 2005

VBScriptで大量のデータ(何百万件ぐらい)を削除するバッチを作成しようと思っています。

Set objConn = CreateObject("ADODB.Connection")
・・・(中略)・・・
objConn.Execute "delete XXX〜〜"

でやると、やはり「時間切れになりました」と怒られました。

=================================
ConnectionTimeoutを使ってみましょう:
=================================

Set objConn = CreateObject("ADODB.Connection")
objConn.ConnectionTimeout = 600
・・・(中略)・・・
objConn.Execute "delete XXX〜〜"

という感じで1行を追加しましたが、全く効きませんでした。

=================================
やはり「ADODB.Command」を使わないといけないみたいですね:
=================================
タイムアウト時間の設定方法を教えてください –DAO、ADO、SQL & Access フォーラム–
↑を参考させていただきました。「ADODB.Command」を使うのが正解ですね。
という感じで、

Set objConn = CreateObject("ADODB.Connection")
Set objCmd = CreateObject("ADODB.Command")
objConn.ConnectionTimeout = 600
objCmd.CommandTimeout = 600
・・・(中略)・・・
objCmd.ActiveConnection = objConn
objCmd.CommandText = "delete XXX〜〜"
objCmd.Execute

で実行すると、無事にタイムアウトせず正常終了しました。
おかげさまです。

scriptaculous.jsでSortableを実装する時、onStartとonEndが拾えますか。

scriptaculous.js(v1.8.1)を使ってソート可能なリストを実装しています。

Sortable.createでonChangeとonUpdateが拾えますが、
ドラッグの開始時と終了時に、onStartとonEndみたいなイベントも拾いたいんですが、うまくいきませんでした。

→ とりあえずdragdrop.jsに手を入れることにしました。

576: var SortableObserver = Class.create({
577:   initialize: function(element, observer) {
578:     this.element   = $(element);
579:     this.observer  = observer;
580:     this.lastValue = Sortable.serialize(this.element);
581:   },
582:
583:   onStart: function() {
584:     this.lastValue = Sortable.serialize(this.element);
// -> ここにドラッグ開始時の処理を書きます
585:   },
586:
587:   onEnd: function() {
588:     Sortable.unmark();
589:     if(this.lastValue != Sortable.serialize(this.element))
590:       this.observer(this.element)
// -> ここにドラッグ終了時の処理を書きます
591:   }
592: });

という感じで、一応機能としては動いていますが、あまりソースには手を入れたくないですね。。。

Draggableオブジェクト作成時にはstarteffectとendeffectが使えますが、Sortableには似たようなものがありますかね。。。