PHPとJavaScriptとLSLのURLエンコードについて動作をまとめてみた

プログラミング
スポンサーリンク

はじめに

こんにちはー!

今日は、URLエンコードの勉強をしたいと思います。なぜ今なのかというと、最近IoT関係でデータを渡したりやりとりするさいにGETをよく使うのですが、このような場合にURLエンコードを使いたいからです。

というわけで、仕様とか含めて調査していきます。まずPHPから調査してみます。

PHPのURLエンコードについて

文字コードについて

はじめに

PHPには、URLエンコードをする関数が用意されています。これを使えばURLエンコードができると思うのですが、変換する前の文字コードってどうなるんだという素朴な疑問点がうかびました。というわけで先に文字コードについて調査してみます。

以下のURLエンコード用の関数を確認します。

実験環境は以下の通り

  • PHP : Server: Apache/2.4.37 (Win32) OpenSSL/1.1.1a PHP/7.3.0, IE 11.472.17134.0

実験1 – デフォルトの文字コードを調査

ソースコードの文字コードは、UTF-8(BOM無し)で保存。

<?php
$text = "abc あいうえお";
echo $text . "<br />";
echo urlencode($text) . "<br />";
echo rawurlencode($text) . "<br />";
?>

これをWebサイトで表示させました。

abc あいうえお
abc+%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
abc%20%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A

HTMLのウェブサイトの文字コードはUTF-8になっており、文字のURLエンコードも「あ」が「%E3%81%82」つまり「0xE3 0x81 0x82」なので、UTF-8の文字コードを変換していることがわかります。

実験2 – phpのソースコードの文字コードを変えてみる

default_charset がUTF-8になっていたため、実験1のような動作になった可能性があります。というわけで、次は以下のようなコードを、Shift_JIS(Windows-31J)で保存。

<?php
header("Content-type: text/html; charset=Windows-31J");
$text = "abc あいうえお";
echo $text . "<br />";
echo urlencode($text) . "<br />";
echo rawurlencode($text) . "<br />";
?>

php.iniも一応以下のように変更。

mbstring.language=Japanese
mbstring.detect_order=SJIS
mbstring.internal_encoding=SJIS
mbstring.http_output=SJIS
mbstring.encoding_translation=On

これをWebサイトで表示させました。

abc あいうえお
abc+%82%A0%82%A2%82%A4%82%A6%82%A8
abc%20%82%A0%82%A2%82%A4%82%A6%82%A8

HTMLのウェブサイトの文字コードは、Shift_JIS(Windows-31J)となり、文字のURLエンコードも「あ」が「%82%a0」つまり「0x82a0」から、Shift_JISでエンコードされたことが分かります。

結果

phpのURLエンコードは、phpの文字コードによって変化することが分かりました。

デフォルトはUTF-8なので、通常はUTF-8を使っていればいいですが、もしShift_JISのphpに対してデータを送りたい場合は、Shift_JISで変換する必要があるようです。現在はそのようなサイトは数少ないと思うため問題ないとは思いますが、確認できるなら確認したほうがよいと思われます。

URLエンコードについて

はじめに

いよいよURLエンコードがどのように変換されるか調べてみましょう。

関数の解説サイトには次のような説明がありました。rawurlencodeの関数の説明には、URLエンコードは、RFC 3986にそっている。PHP 5.3.0 より前のバージョンは、RFC 1738にそっている。urlencodeとの違いは、urlencodeはRFCに対して厳密ではなく、スペースが%20ではなく+記号に置き換わるとのことです。

実際に動作させて変換後の結果をみてみましょう。

ソースコード

<?php
$text = "";
$text .= "<table>";
$text .= "<caption>URLエンコード結果一覧</caption>";
$text .= "<tr>";
$text .= "<th>10進数</th>";
$text .= "<th>16進数</th>";
$text .= "<th>文字</th>";
$text .= "<th>urlencode</th>";
$text .= "<th>rawurlencode</th>";
$text .= "</tr>";
for($charcode = 0; $charcode < 128 ; $charcode++ ) {
	$text .= "<tr>";
	$text .= sprintf("<td>%d</td><td>0x%02X</td><td>%c</td><td>%s</td><td>%s</td>",
		$charcode,
		$charcode,
		$charcode,
		urlencode(chr($charcode)),
		rawurlencode(chr($charcode)),
	);
	$text .= "</tr>";
}
$text .= "</table>";
echo $text;
?>

実行結果

URLエンコード結果一覧

10進数16進数文字urlencoderawurlencode
00x00?%00%00
10x01?%01%01
20x02?%02%02
30x03?%03%03
40x04?%04%04
50x05?%05%05
60x06?%06%06
70x07?%07%07
80x08?%08%08
90x09?%09%09
100x0A?%0A%0A
110x0B?%0B%0B
120x0C?%0C%0C
130x0D?%0D%0D
140x0E?%0E%0E
150x0F?%0F%0F
160x10?%10%10
170x11?%11%11
180x12?%12%12
190x13?%13%13
200x14?%14%14
210x15?%15%15
220x16?%16%16
230x17?%17%17
240x18?%18%18
250x19?%19%19
260x1A?%1A%1A
270x1B?%1B%1B
280x1C?%1C%1C
290x1D?%1D%1D
300x1E?%1E%1E
310x1F?%1F%1F
320x20+%20
330x21!%21%21
340x22%22%22
350x23#%23%23
360x24$%24%24
370x25%%25%25
380x26&%26%26
390x27%27%27
400x28(%28%28
410x29)%29%29
420x2A*%2A%2A
430x2B+%2B%2B
440x2C,%2C%2C
450x2D
460x2E...
470x2F/%2F%2F
480x30000
490x31111
500x32222
510x33333
520x34444
530x35555
540x36666
550x37777
560x38888
570x39999
580x3A:%3A%3A
590x3B;%3B%3B
600x3C<%3C%3C
610x3D=%3D%3D
620x3E>%3E%3E
630x3F?%3F%3F
640x40@%40%40
650x41AAA
660x42BBB
670x43CCC
680x44DDD
690x45EEE
700x46FFF
710x47GGG
720x48HHH
730x49III
740x4AJJJ
750x4BKKK
760x4CLLL
770x4DMMM
780x4ENNN
790x4FOOO
800x50PPP
810x51QQQ
820x52RRR
830x53SSS
840x54TTT
850x55UUU
860x56VVV
870x57WWW
880x58XXX
890x59YYY
900x5AZZZ
910x5B[%5B%5B
920x5C\%5C%5C
930x5D]%5D%5D
940x5E^%5E%5E
950x5F___
960x60`%60%60
970x61aaa
980x62bbb
990x63ccc
1000x64ddd
1010x65eee
1020x66fff
1030x67ggg
1040x68hhh
1050x69iii
1060x6Ajjj
1070x6Bkkk
1080x6Clll
1090x6Dmmm
1100x6Ennn
1110x6Fooo
1120x70ppp
1130x71qqq
1140x72rrr
1150x73sss
1160x74ttt
1170x75uuu
1180x76vvv
1190x77www
1200x78xxx
1210x79yyy
1220x7Azzz
1230x7B{%7B%7B
1240x7C|%7C%7C
1250x7D}%7D%7D
1260x7E~%7E~
1270x7F?%7F%7F

結果

URLエンコードをすることで、制御文字はほぼ変換されました。

変換されていない記号は以下の通り。

  • +(※rawurlencodeでは変換される)
  • -(ハイフン)
  • .(ドット)
  • _(アンダーバー)
  • ~(※rawurlencodeでは変換されない)

URLデコードについて

urlencoderawurlencodeの互換性を調べたいと思います。

デコードを組み合わせて以下のコードで確認しました。

<?php
echo "\"" . urldecode("%20") . "\"<br>";
echo "\"" . rawurldecode("+") . "\"<br>";
echo "\"" . urldecode("~") . "\"<br>";
echo "\"" . rawurldecode("%7E") . "\"<br>";
?>

結果は、

" "
"+"
"~"
"~"

このようになりました。

+に関しては、rawurldecodeで元に戻せません。つまり、urlencodeで変換した文字は、rawurldecodeで元に戻せないことなります。逆なら大丈夫なので、urldecodeであれば問題ありません。

urlencoderawurlencodeか、どちらを使えばいいのでしょうか。これについては、最後に記載したいと思います。ちなみに、JavaScriptにあるencodeURIComponentによると

application/x-www-form-urlencoded によれば、スペースは ‘+’ に置換されます。そのため、encodeURIComponentによる置換に加えて “%20” を “+” に変換したいと考えるユーザーもおられるでしょう。

encodeURIComponent() – MDN – Mozillaen より抜粋

と記載があります。これはどういう意味かといいますと、Webページでデータを投稿する際のURLエンコードは、スペースは ‘+’ にするという決まりがあるのです。そのため、urlencodeによるエンコード方法は非推奨とかではなく、普通に利用されている関数なのです。

JavaScriptのURLエンコードについて

文字コードについて

はじめに

データを渡す際などに利用するJavaScriptの動作を調べてみましょう。

JavaScript用のURLエンコード用関数を確認します。

実験1 – デフォルトの文字コードを調査

htmlの文字コードは、UTF-8(BOM無し)で保存。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
const text = "abc あいうえお";
console.log(escape(text));
console.log(encodeURI(text));
console.log(encodeURIComponent(text));
const params = new URLSearchParams();
params.set("", "abc あいうえお")
console.log(params.toString());
</script> 
</body>
</html>

Chrome 71.0.3578.98 での結果は、

sample.html:9 abc%20%u3042%u3044%u3046%u3048%u304A
sample.html:10 abc%20%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
sample.html:11 abc%20%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
sample.html:14 =abc+%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A

Microsoft EdgeHTML 17.17134 での結果は、

abc%20%u3042%u3044%u3046%u3048%u304A
abc%20%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
abc%20%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
=abc+あいうえお

escapeでは、「あ」を0x3042に変換しています。これはどうやらUTF-16になっているようです。

サロゲートペアのツチヨシ「𠮷」を試してみましょう。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
const text = "𠮷";
console.log(escape(text));
console.log(encodeURI(text));
console.log(encodeURIComponent(text));
const params = new URLSearchParams();
params.set("", text)
console.log(params.toString());
</script> 
</body>
</html>

Chrome及びEdgeでの結果は、

sample.html:9 %uD842%uDFB7
sample.html:10 %F0%A0%AE%B7
sample.html:11 %F0%A0%AE%B7
sample.html:14 =%F0%A0%AE%B7

escapeではやはり、UTF-16を使用しているようです。encodeURIencodeURIComponentURLSearchParamsは、UTF-8を使用しています。

実験2 – HTMLの文字コードを変えた場合

phpと同じように、ファイルの文字コードの依存する可能性があるため確認します。

以下のようなコードを、Shift_JIS(Windows-31J)で保存。

<!DOCTYPE html>
<html>
<head>
<meta charset="Shift_JIS">
</head>
<body>
<script type="text/javascript">
const text = "abc あいうえお";
console.log(escape(text));
console.log(encodeURI(text));
console.log(encodeURIComponent(text));
const params = new URLSearchParams();
params.set("", text);
console.log(params.toString());
</script> 
</body>
</html>

Chrome 71.0.3578.98 での結果は、

sample.html:9 abc%20%uFFFD%uFFFD%uFFFD%uFFFD%uFFFD%uFFFD%uFFFD%uFFFD%uFFFD%uFFFD
sample.html:10 abc%20%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD
sample.html:11 abc%20%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD
sample.html:14 =abc+%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD%EF%BF%BD

Microsoft EdgeHTML 17.17134 での結果は、

abc%20%u3042%u3044%u3046%u3048%u304A
abc%20%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
abc%20%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
=abc+あいうえお

Chromeですが文字エンコードに失敗しているようです。原因について分かりませんでした。Edgeに関しては、UTF-8で変換しているようです。

Chromeでうまく動かなかったので、UTF-16 Little Endianで試しました。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-16le">
</head>
<body>
<script type="text/javascript">
const text = "abc あいうえお";
console.log(escape(text));
console.log(encodeURI(text));
console.log(encodeURIComponent(text));
const params = new URLSearchParams();
params.set("", text);
console.log(params.toString());
</script> 
</body>
</html>

Chrome 71.0.3578.98 での結果は、

sample.html:9 abc%20%u3042%u3044%u3046%u3048%u304A
sample.html:10 abc%20%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
sample.html:11 abc%20%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A
sample.html:14 =abc+%E3%81%82%E3%81%84%E3%81%86%E3%81%88%E3%81%8A

上記の結果から、HTMLの文字コードは関係なく、UTF-8に変換されることが分かりました。

結果

escapeについては非推奨なので、動作は分からないです。ただ、encodeURIencodeURIComponentURLSearchParamsに関していえば、UTF-8に変換してくれます。ただChromeの動作を考えると、HTMLを記載する際は、Unicodeを使ったほうがよさそうです。

URLエンコードについて

はじめに

escapeencodeURIencodeURIComponentURLSearchParamsがどのように変換するか確認します。

ソースコード

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
let text = "";
text += "<table>";
text += "<caption>URLエンコード結果一覧</caption>";
text += "<tr>";
text += "<th>10進数</th>";
text += "<th>16進数</th>";
text += "<th>文字</th>";
text += "<th>escape</th>";
text += "<th>encodeURI</th>";
text += "<th>encodeURIComponent</th>";
text += "<th>URLSearchParams</th>";
text += "</tr>";
for(let charcode = 0; charcode < 128 ; charcode++ ) {
	const chardata = String.fromCharCode(charcode);
	text += "<tr>";
	text += "<td>" + charcode + "</td>";
	text += "<td>0x" + charcode.toString(16).toUpperCase() + "</td>";
	text += "<td>" + chardata + "</td>";
	text += "<td>" + escape(chardata) + "</td>";
	text += "<td>" + encodeURI(chardata) + "</td>";
	text += "<td>" + encodeURIComponent(chardata)  + "</td>";
	text += "<td>" + (new URLSearchParams({"":chardata})).toString().substr(1) + "</td>";
	text += "</tr>";
}
text += "</table>";
document.body.insertAdjacentHTML("beforeend", text);
</script> 
</body>
</html>

実行結果

URLエンコード結果一覧

10進数16進数文字escapeencodeURIencodeURI
Component
URL
Search
Params
00x0?%00%00%00%00
10x1?%01%01%01%01
20x2?%02%02%02%02
30x3?%03%03%03%03
40x4?%04%04%04%04
50x5?%05%05%05%05
60x6?%06%06%06%06
70x7?%07%07%07%07
80x8?%08%08%08%08
90x9?%09%09%09%09
100xA?%0A%0A%0A%0A
110xB?%0B%0B%0B%0B
120xC?%0C%0C%0C%0C
130xD?%0D%0D%0D%0D
140xE?%0E%0E%0E%0E
150xF?%0F%0F%0F%0F
160x10?%10%10%10%10
170x11?%11%11%11%11
180x12?%12%12%12%12
190x13?%13%13%13%13
200x14?%14%14%14%14
210x15?%15%15%15%15
220x16?%16%16%16%16
230x17?%17%17%17%17
240x18?%18%18%18%18
250x19?%19%19%19%19
260x1A?%1A%1A%1A%1A
270x1B?%1B%1B%1B%1B
280x1C?%1C%1C%1C%1C
290x1D?%1D%1D%1D%1D
300x1E?%1E%1E%1E%1E
310x1F?%1F%1F%1F%1F
320x20%20%20%20+
330x21!%21!!%21
340x22%22%22%22%22
350x23#%23#%23%23
360x24$%24$%24%24
370x25%%25%25%25%25
380x26&%26&%26%26
390x27%27%27
400x28(%28((%28
410x29)%29))%29
420x2A*****
430x2B+++%2B%2B
440x2C,%2C,%2C%2C
450x2D
460x2E.....
470x2F///%2F%2F
480x3000000
490x3111111
500x3222222
510x3333333
520x3444444
530x3555555
540x3666666
550x3777777
560x3888888
570x3999999
580x3A:%3A:%3A%3A
590x3B;%3B;%3B%3B
600x3C<%3C%3C%3C%3C
610x3D=%3D=%3D%3D
620x3E>%3E%3E%3E%3E
630x3F?%3F?%3F%3F
640x40@@@%40%40
650x41AAAAA
660x42BBBBB
670x43CCCCC
680x44DDDDD
690x45EEEEE
700x46FFFFF
710x47GGGGG
720x48HHHHH
730x49IIIII
740x4AJJJJJ
750x4BKKKKK
760x4CLLLLL
770x4DMMMMM
780x4ENNNNN
790x4FOOOOO
800x50PPPPP
810x51QQQQQ
820x52RRRRR
830x53SSSSS
840x54TTTTT
850x55UUUUU
860x56VVVVV
870x57WWWWW
880x58XXXXX
890x59YYYYY
900x5AZZZZZ
910x5B[%5B%5B%5B%5B
920x5C\%5C%5C%5C%5C
930x5D]%5D%5D%5D%5D
940x5E^%5E%5E%5E%5E
950x5F_____
960x60`%60%60%60%60
970x61aaaaa
980x62bbbbb
990x63ccccc
1000x64ddddd
1010x65eeeee
1020x66fffff
1030x67ggggg
1040x68hhhhh
1050x69iiiii
1060x6Ajjjjj
1070x6Bkkkkk
1080x6Clllll
1090x6Dmmmmm
1100x6Ennnnn
1110x6Fooooo
1120x70ppppp
1130x71qqqqq
1140x72rrrrr
1150x73sssss
1160x74ttttt
1170x75uuuuu
1180x76vvvvv
1190x77wwwww
1200x78xxxxx
1210x79yyyyy
1220x7Azzzzz
1230x7B{%7B%7B%7B%7B
1240x7C|%7C%7C%7C%7C
1250x7D}%7D%7D%7D%7D
1260x7E~%7E~~%7E
1270x7F?%7F%7F%7F%7F

結果

encodeURIは、記号のいくつかが変換されていません。例えば、&とかです。これは、URL上で特別な意味を持つため、変換するとURLとしての特別な意味をなくしてしまいます。これはどういった場面を想定しているのでしょうか。URL全体のデータに対して、エンコードした後に、エンコード後のURLに対してアクセスまで行うといったことを想定しているのかもしれません。

encodeURIComponentは、&などURL上で特殊な意味をもつ記号も変換されています。つまり、GETなどでデータを入れるように文字列を変換したいという場合を想定しています。

URLSearchParamsは、多くの記号をURLエンコードしてくれますが、半角スペースの +に変換していたり、チルダを%7Eに変換するなど一部動作が異なる処理をしています。これはPHPのurlencodeと同一の動作となっております。

URLデコードについて

本当は比較のためにURLSearchParamsを使って、URLデコードをしたかったのですが、よくわからなかったので以下のような感じで調査します。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
let text = "_%20_+_%7E_~_";
let html = "";
html += unescape(text) + "<br>";
html += decodeURI(text) + "<br>";
html += decodeURIComponent(text) + "<br>";
html += decodeURIComponent(text.replace(/\+/g, "%20")) + "<br>";
document.body.insertAdjacentHTML("beforeend", html);
</script> 
</body>
</html>

結果は以下の通り

_ _+_~_~_
_ _+_~_~_
_ _+_~_~_
_ _ _~_~_

+ に変換したい場合は、通常の関数だけでは変換できなので、予めreplace(/\+/g, "%20")のように、+をスペースに置換後に関数にかけるという手がよいかもしれません。

リンデンスクリプト言語

はじめに

おまけですが、セカンドライフ上で動作するリンデンスクリプト(Linden Scripting Language)でも確認してみました。

URLエンコードについて

スクリプト

以下を実行します。ASCIIコードから文字への変換関数がなかったので、作りました。

string toUrlCode(integer x) {
	string HEX_MAP = "0123456789ABCDEF";
	if(x < 0x10) {
		return "%0" + llGetSubString(HEX_MAP, x, x);
	}
	else {
		return "%" + llGetSubString(HEX_MAP, x >> 4, x >> 4) + llGetSubString(HEX_MAP, x & 0xF, x & 0xF);
	}
}

string fromCharCode(integer x) {
	return llUnescapeURL(toUrlCode(x));
}

default {
	state_entry() {
		string text = "";
		integer charcode = 0;
		for(charcode = 0;charcode < 128;charcode++) {
			text += llEscapeURL(fromCharCode(charcode)) + "\n";
		}
		llOwnerSay(text);
	}
}

実行結果

URLエンコード結果一覧

10進数16進数文字llEscapeURL
00x0??
10x1?%01
20x2?%02
30x3?%03
40x4?%04
50x5?%05
60x6?%06
70x7?%07
80x8?%08
90x9?%09
100xA?%0A
110xB?%0B
120xC?%0C
130xD?%0D
140xE?%0E
150xF?%0F
160x10?%10
170x11?%11
180x12?%12
190x13?%13
200x14?%14
210x15?%15
220x16?%16
230x17?%17
240x18?%18
250x19?%19
260x1A?%1A
270x1B?%1B
280x1C?%1C
290x1D?%1D
300x1E?%1E
310x1F?%1F
320x20%20
330x21!%21
340x22%22
350x23#%23
360x24$%24
370x25%%25
380x26&%26
390x27%27
400x28(%28
410x29)%29
420x2A*%2A
430x2B+%2B
440x2C,%2C
450x2D%2D
460x2E.%2E
470x2F/%2F
480x3000
490x3111
500x3222
510x3333
520x3444
530x3555
540x3666
550x3777
560x3888
570x3999
580x3A:%3A
590x3B;%3B
600x3C<%3C
610x3D=%3D
620x3E>%3E
630x3F?%3F
640x40@%40
650x41AA
660x42BB
670x43CC
680x44DD
690x45EE
700x46FF
710x47GG
720x48HH
730x49II
740x4AJJ
750x4BKK
760x4CLL
770x4DMM
780x4ENN
790x4FOO
800x50PP
810x51QQ
820x52RR
830x53SS
840x54TT
850x55UU
860x56VV
870x57WW
880x58XX
890x59YY
900x5AZZ
910x5B[%5B
920x5C\%5C
930x5D]%5D
940x5E^%5E
950x5F_%5F
960x60`%60
970x61aa
980x62bb
990x63cc
1000x64dd
1010x65ee
1020x66ff
1030x67gg
1040x68hh
1050x69ii
1060x6Ajj
1070x6Bkk
1080x6Cll
1090x6Dmm
1100x6Enn
1110x6Foo
1120x70pp
1130x71qq
1140x72rr
1150x73ss
1160x74tt
1170x75uu
1180x76vv
1190x77ww
1200x78xx
1210x79yy
1220x7Azz
1230x7B{%7B
1240x7C|%7C
1250x7D}%7D
1260x7E~%7E
1270x7F?%7F

※NUL文字はLSL上では利用できないため変換を確かめることができませんでした。

結果

 +に変換せず、そのまま%20にURLエンコードしています。URLエンコードしておけば、元のスペースに戻るので特に気にする必要はありません。

URLデコードについて

デコードの方も少し確認してみました。

default {
	state_entry() {
		llOwnerSay(llUnescapeURL("_%20_+_"));
	}
}

実行結果は以下の通り

_ _+_

llEscapeURLの仕様から++のままですね。他の言語で +に変換してしまうと元に戻せなくなるので注意が必要です。

おわりに

今回、PHPとJavaScriptとLSLのURLエンコードについて実際の動作を確認してみました。

以下、結論となります。

文字コードについて

URLエンコードにおいては、JavaScriptの仕様からUTF-8が基本となるようです。

PHPは、ソースコードの文字コードによって内部動作が変わるため、必ずUTF-8を使用したほうがよいです。また、Chromeに至ってもURLエンコードが正しく動作しない可能性があるため、HTMLの文字コードはUTF-8を使用しましょう。

URLエンコードの方法

送信先の仕様が分かっているのであれば、方式を合わせるのが最も良いです。

Webページのフォームなどで利用される可能性があるなら、Webページのサブミットで利用される変換方法(application/x-www-form-urlencoded)、つまり半角スペースの +に変換、チルダを%7Eに変換する方法をとりましょう。

  • php ー  urlencode及び、urldecode
  • JavaScirptURLSearchParams(※IE11は使用不可)

URLSearchParamsは動かない環境もあるため、replace(/%20/g, "+")のようなものを挟み込んでおけばよいと思われます。

データをURL上でやりとりしたいという理由であれば、以下の関数を使いましょう。

  • php ー  rawurlencode及び、rawurldecode
  • JavaScirptー encodeURIComponent及び、decodeURIComponent

一部SQLなどに直接食わせたりすると危険な文字列とかあるので、デコード後は必要に応じて加工が必要かと思います。

コメント

タイトルとURLをコピーしました