Tag Archive server

เซ็ต SSL เร็วและฟรีใน 5 นาที

ตั้งแต่ google ใช้ SSL ออกมาเป็นเงื่อนไขในการทำ SEO ทำให้ทุกเว็บต้องมาเปิดใช้ SSL ไม่งั้นอันดับจะตกลง

สามารถขอ SSL ฟรีได้ง่ายๆ โดยใช้บริการของ http://Let’s Encrypt’s เปิดให้ใช้ฟรีหรือจะบริจาคเล็กน้อยตามศรัทธาก็ได้ การติดตั้งง่ายๆ โดย

  • Web Hosting who support Let’s Encrypt จะเป็น host ที่ support อยู่แล้วสามารถเปิดใช้ได้เลยอย่าง hostgator.com
  • ใช้ certbot instructions เลือกว่าใช้ Apache, Haproxy, Nginx, Plesk และ os ที่ใช้อย่าง Arch Linux, CentOS 6, Debian, Fedora, FreeBSD, Gentoo, macOS, OpenBSD 6.0+, openSUSE, RHEL, Ubuntu, Windows มันจะบอกวิธิติดตั้งมาให้ภายใน 5 นาทีเว็บก็ใช้ SSL ได้เลยทุก domain !!!

อย่าง server ผมก็ทำแค่ SSH เข้าไปที่ host แล้วพิมพ์ตาม

sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --apache
sudo certbot certonly --apache

แล้วทดลองเรียกเว็บโดยใช้ SSL เท่านั้นเอง ง่ายจริงๆ

php: download ไฟล์จาก server

ตัวอย่าง code php ไว้ download ไฟล์จาก server

PHP/download.php
<?php
$fileDir = '../assets/';
$token = 'HH89VOiirgXlCdEqDrFs';

if ($_REQUEST['token'] != $token) {
    exit('bad token');
}

$file = $fileDir . $_REQUEST['file'];
if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: ' . mime_content_type($file));
    header('Content-Disposition: attachment; filename="' . basename($file) . '"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));

    //readfile($file);
    echo file_get_contents($file);
} else {
    exit('file not found');
}

เพราะว่า ออกแบบให้สามารถโหลดไฟล์อะไรก็ได้จาก server เลยมีการใช้ token ช่วยในการตรวจสอบความปลอดภัยเล็กน้อย ของจริงต้องแก้ให้ตรวจ token ซับซ้อนกว่านี้เพื่อความปลอดภัย

curl: ดาวน์โหลดไฟล์

การใช้ curl ไป download file จากเซิร์ฟเวอร์อื่นๆ ไม่ได้ซับซ้อนเหมือนการอัพโหลดในตัวอย่าง curl: ส่งไฟล์ การทำงานค่อนข้างตรงไปตรงมาก คือ มีไฟล์ที่มี code curl ทำหน้าที่ request และมีไฟล์หรือโปรแกรมที่ทำหน้าที่จ่ายไฟล์ให้ โดยดัดแปลงให้แสดง error กลับมาในรูปแบบที่ง่ายกับการแสดง error ในฝั่งรีเควสท์

เพื่อความปลอดภัย จะมีการเขียนการตรวจสอบเล็กน้อย

  • จะส่ง token มาและทั้ง 2 ไฟล์จะต้องมีค่าเท่าๆกัน ในความเป็นจริง ควรจะมีการเขียนที่ดีกว่านี้ เช่น เปลี่ยน token ตามช่วงเวลา
  • ไม่ควรให้ร้องขอไฟล์โดยใช้ full path และเพื่อป้องกันการใช้ฝั่งรับในการ download ไฟล์อื่นๆ จึงต้องกำหนดโฟลเดอร์เริ่มต้นไว้ให้ดาวน์โหลดไฟล์ในโฟลเดอร์ที่กำหนดไว้เท่านั้น
  • [code language=”php” title=”curl_download.php”]<?php
    header(‘Cache-Control: no-cache, no-store, must-revalidate’);
    header(‘Expires: 0’);
    header(‘Pragma: no-cache’);

    $post = [
    ‘file’ => ‘test.docx’,
    ‘token’ => $token,
    ];
    $token = ‘HH89VOiirgXlCdEqDrFs’;
    $url = ‘http://localhost/snippets/PHP/download.php’;

    $ch = curl_init();

    curl_setopt_array($ch, [
    CURLOPT_ENCODING => ‘UTF-8’,
    CURLOPT_FRESH_CONNECT => true,
    CURLOPT_POST => 1,
    CURLOPT_POSTFIELDS => http_build_query($post),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_URL => $url,
    ]);

    $result = curl_exec($ch);

    switch ($result) {
    case ‘bad token’:{
    curl_close($ch);
    exit(‘check token in ‘ . $url);
    }break;

    case ‘file not found’:{
    curl_close($ch);
    exit(‘file not found in target server.’);
    }break;

    default:{
    header(‘Content-Disposition: attachment; filename="’ . $post[‘file’]);
    echo $result;
    }
    }
    curl_close($ch);[/code]

    [code language=”php” title=”download.php”]<?php
    $fileDir = ‘../assets/’;
    $token = ‘HH89VOiirgXlCdEqDrFs’;

    if ($_REQUEST[‘token’] != $token) {
    exit(‘bad token’);
    }

    $file = $fileDir . $_REQUEST[‘file’];
    if (file_exists($file)) {
    header(‘Content-Description: File Transfer’);
    header(‘Content-Type: ‘ . mime_content_type($file));
    header(‘Content-Disposition: attachment; filename="’ . basename($file) . ‘"’);
    header(‘Expires: 0’);
    header(‘Cache-Control: must-revalidate’);
    header(‘Pragma: public’);
    header(‘Content-Length: ‘ . filesize($file));

    //readfile($file);
    echo file_get_contents($file);
    } else {
    exit(‘file not found’);
    }
    [/code]

curl: ส่งไฟล์

และแล้วก็มาถึงจุดที่รอคอย การส่งไฟล์ด้วย curl เหมือนที่ user upload ไฟล์เข้าเว็บ เหมาะกับการเอาไปเขียนโปรแกรมทรานสเฟอร์ไฟล์จากเว็บหนึ่งไปอีกที่หนึ่ง หรือจะเขียน bot ส่งไฟล์ออกไปเก็บเป็นข้อมูลสำรองก็ได้

[code language=”php” title=”curl_file.php”]<!doctype html>
<html>

<head>
<meta charset="utf-8">
<title>CURL: send file</title>
<link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
</head>

<body>
<div class="container">
<?php
if (count($_FILES) || count($_POST)) {
$url = ‘http://localhost/snippets/PHP/variables.php’;

if (count($_FILES)) {
$file_name_with_full_path = $_FILES[‘avatar’][‘tmp_name’];

if (function_exists(‘curl_file_create’)) {
/* php 5.5+ */
$_POST[‘avatar’] = curl_file_create($file_name_with_full_path);
} else {
$_POST[‘avatar’] = ‘@’ . realpath($file_name_with_full_path);
}
}

$ch = curl_init();

curl_setopt_array($ch, [
CURLOPT_ENCODING => ‘UTF-8’,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $_POST,
//CURLOPT_POSTFIELDS => http_build_query($_POST),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => $url,
]);

$result = curl_exec($ch);
curl_close($ch);

echo $result;
}
?>
<form action="curl_file.php" enctype="multipart/form-data" method="post">
<div class="form-group">
<label for="name">Name:</label>
<input class="form-control" id="name" name="name" type="text">
</div>
<div class="form-group">
<label for="avatar">Avatar:</label>
<input accept="image/gif, image/jpeg, image/x-png" class="form-control" id="avatar" name="avatar" type="file">
</div>
<div class="form-group">
<label for="address1">text address:</label>
<input class="form-control" id="address1" name="address[d]" type="text">
</div>
<div class="form-group">
<label for="address2">text address 2:</label>
<input class="form-control" id="address2" name="address[f]" type="text">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</body>

</html>[/code]

แต่เพราะ bug ของ function http_build_query ไม่สามารถ encoded query string ในกรณีที่มีไฟล์ได้อย่างถูกต้อง ทำให้ต้องส่งค่าฟอร์มไปโดยไม่เข้ารหัส ดังนั้น ค่าที่เป็น array จึงส่งค่าออกไปผิด[code language=”php” title=”function http_build_query bug”][address]Array
(
[name] => pitt phunsanit
[address] => Array
)[/code]

จากที่ค้นหาข้อมูลดู ยังไม่มีวิธีที่แก้ปัญหานี้ได้โดยไม่มีผลอาการข้างเคียง คงต้องรอให้ทางทีมงานพัฒนา PHP แก้ปัญหาให้ ตอนนี้ก็พยามหลีกเลี่ยงการส่งข้อมูลแบบเป็นอาร์เรไปก่อน อาจจะใช้ implode รวมข้อมูลก่อนส่งไปก็ได้

curl: ส่ง ฟอร์มแบบ post

หลังจากตัวอย่าง curl: ส่ง ฟอร์มแบบ get เรามาลองส่งข้อมูลแบบโพสต์กันต่อ เว็บไซต์ส่วนใหญ่จะนิยมส่งค่าในแบบฟอร์มแบบ post มากกว่าแบบ get เพราะว่า url จะดูสวยงาม ไม่เละเทะ ดูแล้วสบายตา และปลอดภัยกว่าการส่ข้อมูลให้เห็นง่ายๆ แบบใช้ url

[code language=”php” title=”curl_post.php”]<!doctype html>
<html>

<head>
<meta charset="utf-8">
<title>CURL: send post variables</title>
<link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
</head>

<body>
<div class="container">
<?php
if (count($_POST)) {
$url = ‘http://localhost/snippets/PHP/variables.php’;

$ch = curl_init();

curl_setopt_array($ch, [
CURLOPT_ENCODING => ‘UTF-8’,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => http_build_query($_POST),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => $url,
]);

$result = curl_exec($ch);
curl_close($ch);

echo $result;
}
?>
<form action="curl_post.php" enctype="multipart/form-data" method="post">
<div class="form-group">
<label for="name">Name:</label>
<input class="form-control" id="name" name="name" type="text">
</div>
<div class="form-group">
<label for="avatar">Avatar:</label>
<input accept="image/gif, image/jpeg, image/x-png" class="form-control" id="avatar" name="avatar" type="file">
</div>
<div class="form-group">
<label for="address1">text address:</label>
<input class="form-control" id="address1" name="address[]" type="text">
</div>
<div class="form-group">
<label for="address2">text address 2:</label>
<input class="form-control" id="address2" name="address[]" type="text">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</body>

</html>[/code]

จากการเปลี่ยน option ของ curl เล็กน้อยการส่งข้อมูลก็เปลี่ยนไปเป็นแบบ method post แล้ว แต่ก็ยังส่งไฟล์ไปไม่ได้อยู่ดีๆ ใจเย็นๆ ครับบทความหน้าส่งไฟล์ออกไปแน่ๆ ครับ

curl: ส่ง ฟอร์มแบบ get

curl หรือ Client URL Library เป็น function ที่ทำให้ php ทำตัวเป็น browser ที่ใช้เปิดเว็บรับส่งข้อมูลต่างๆ จาก server ของเราไปเซิฟเวอร์เครื่องอื่นๆ

ตัวอย่างการใช้งานที่ง่ายที่สุด คือการใช้ curl โดยการจำลองการส่งข้อมูลจากฟอร์มแบบเมธอดเก็ต หรือที่เรียกง่ายๆว่า ส่งข้อมูลแบบ url นั่นละ

[code language=”php” title=”curl_get.php”]<!doctype html>
<html>

<head>
<meta charset="utf-8">
<title>CURL: send get variables</title>
<link href="../vendor/twbs/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css">
</head>

<body>
<div class="container">
<?php
if (count($_GET)) {
$queryString = http_build_query($_GET);
$url = ‘http://localhost/snippets/PHP/variables.php?’ . $queryString;

echo ‘<br>$url = ‘, $url;

$ch = curl_init();

curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_URL => $url,
]);

$result = curl_exec($ch);
curl_close($ch);

echo $result;
}
?>
<form action="curl_get.php" method="get">
<div class="form-group">
<label for="name">Name:</label>
<input class="form-control" id="name" name="name" type="text">
</div>
<div class="form-group">
<label for="avatar">Avatar:</label>
<input accept="image/gif, image/jpeg, image/x-png" class="form-control" id="avatar" name="avatar" type="file">
</div>
<div class="form-group">
<label for="address1">text address:</label>
<input class="form-control" id="address1" name="address[]" type="text">
</div>
<div class="form-group">
<label for="address2">text address 2:</label>
<input class="form-control" id="address2" name="address[]" type="text">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</body>

</html>[/code]ในการแปลงข้อมูลจากแบบฟอร์มจะใช้ [code language=”php” title=”Generate URL-encoded query string”]$queryString = http_build_query($_GET);[/code] แปลงให้อยู่ในรูปแบบคิวรี่สตริงที่ส่งไปกับ url ได้

การทดสอบทำได้โดยไฟล์ variables.php จำลองเป็นฝั่งรับข้อมูล[code language=”php” title=”variables.php”]<?php
echo ‘<h3>$_COOKIE</h3><pre>’, print_r($_COOKIE, true), ‘</pre>’;
echo ‘<h3>$_FILES</h3><pre>’, print_r($_FILES, true), ‘</pre>’;
echo ‘<h3>$_GET</h3><pre>’, print_r($_GET, true), ‘</pre>’;
echo ‘<h3>$_POST</h3><pre>’, print_r($_POST, true), ‘</pre>’;
echo ‘<h3>$_REQUEST</h3><pre>’, print_r($_REQUEST, true), ‘</pre>’;
[/code]

ข้อมูลที่ส่งไปจะแสดงกลับมาให้เราเห็น แต่สังเกตุได้ว่า ถึงจะส่งไฟล์ avatar ฝั่งรับก็จะไม่ได้รับ เพราะการส่งข้อมูลแบบนี้จะมีข้อเสียคือ ไม่สามารถส่งไฟล์ได้

git: private repository โดยใช้ synology server

เดี่ยวนี้ถ้าต้องการจะใช้ git repository ก็แค่สมัครสมาชิกเว็บอย่าง github แค่กรอกข้อมูลใน Join GitHub ไม่นานก็ได้พื้นที่สำหรับ backup ข้อมูลได้แล้ว ติดแค่ว่าถ้าเป็น project ภายในหรือเป็นเรื่องเกี่ยวกับธุรกิจการจะเปิดให้คนอื่นใครก็ได้เข้ามาดู source code คงจะไม่ดีแน่ ทำให้ต้องจ่ายค่าบริการเพื่ิอสร้างเป็น private repository หรืออีกทางเลือกคือ สร้าง git server ไว้ใช้เอง

ผมมีตัว nas ของ synology อยู่แล้วเลยใช้มันเป็นที่สำรองข้อมูลซะเลย จะได้ไม่ต้องสร้าง linux มาทำเป็น server อีกตัว

  1. login เข้า synology Control Panel โดยใช้ user ที่มีสิทธิ administrator
  2. ลง git package โดยวิธี Install or Buy Packages
  3. set user permission ให้ใช้ group git ได้โดยวิธี Manage Groups
  4. เปิดให้ใช้ ssh ได้โดยวิธีตาม Terminal
  5. SSH login synology nas ได้โดยวิธี How to login to DSM with root permission via SSH/Telnet
  6. สร้าง folder ไว้เก็บข้อมูล git ทั้งหมดและเซ็ทสิทธิไว้
    # Create the directory
    mkdir /volume1/git

    # folder owner and permission
    chown -R admin:administrators git
    chmod -R 772 git

  7. เตรียมการสำเร็จแล้ว เราสามารถสร้าง repository ขึ้นมาใหม่ได้โดย
    cd /volume1/git
    git init --bare --shared [my-project].git

    โดยแทนที่

    [my-project]

    โดยชื่อ git project

    ในขั้นตอนนี้ folder [my-project].git จะถูกสร้างขึ้นมาใหม่ใน /volume1/git/ และจะเห็นข้อความประมาณ Initialized empty shared Git repository in /volume1/git/snippets.git/ ก็เป็นอันเสร็จกับทางฝั่ง git server แล้ว

  8. จากนั้นก็ clone git ในเครื่อง client (ฝั่ง local) ได้โดยใช้คำสั่ง
    git clone ssh://[git-user]@[syn-ip-addr]/volume1/git/[my-project].gitโดย
    [git-user]
    user ที่เซ็ตไว้
    [syn-ip-addr]
    ip ของตัว nas synology
    [my-project]
    path และชือ repository

    เช่น
    git clone ssh://ph[email protected]/volume1/git/chromeExtensions/pittBookmarks.git

อาจจะดูยุ่งยากแต่ repository ต่อไปแค่ทำ 2 ขั้นตอนสุดท้าย ก็สามารถทำงานอย่างเป็นส่วนตัวได้แล้ว

ทำ Virtual Host ใน Apache

เพราะว่าต้องแยกส่วนของ frontend และ backend ไว้คนละ server เพื่อความสดวกและปลอดภัย โดยทั้งคู่จะติดต่อกันผ่านทาง api แต่เวลาเขียนมีคอมพิวเตอร์แค่เครื่องเดียว ตามปกติสามารถทำได้โดยแยกงานไว้คนละ folder และเพื่อให้เหมือนของจริงยิ่งขึ้นก็ใข้วิธีทำ Virtual Host แยกออกเป็น 2 เซิร์ฟเวอร์ (ถึงจะแค่เครื่องจำลองก็เถอะ)

ทำได้โดยการเปิดไฟล์ C:\xampp\apache\conf\extra\httpd-vhosts.conf และเพิ่ม[code language=”text” title=”C:\xampp\apache\conf\extra\httpd-vhosts.conf”]

## backend
Listen 81
<VirtualHost *:81>

CustomLog "D:\xampp\htdocs\cms_backend\logs\apacheAccess.txt" common
ErrorLog "D:\xampp\htdocs\cms_backend\logs\apacheError.txt"

php_flag display_errors on
php_flag log_errors on
php_value error_log "D:\xampp\htdocs\cms_backend\logs\phpError.txt"
php_value error_reporting 2147483647

DocumentRoot "D:\xampp\htdocs\cms_backend\www"

ServerAdmin [email protected]
ServerName backend.localhost

</VirtualHost>

## frontend
Listen 82
<VirtualHost *:82>

CustomLog "D:\xampp\htdocs\cms_frontend\logs\apacheAccess.txt" common
ErrorLog "D:\xampp\htdocs\cms_frontend\logs\apacheError.txt"

php_flag display_errors on
php_flag log_errors on
php_value error_log "D:\xampp\htdocs\cms_frontend\logs\phpError.txt"
php_value error_reporting 2147483647

DocumentRoot "D:\xampp\htdocs\cms_frontend\www"

ServerAdmin [email protected]
ServerName frontend.localhost

</VirtualHost>[/code]

อธิบาย

Listen
คือหมายเลขพอร์ตที่จะให้รอรับ request อย่าตั้งให้ชนกับตัวอื่น
CustomLog, ErrorLog
คือไฟล์ log ที่แยกออกมาของแต่ละ virtual host โดยสามารถอ่านคู่มือได้จาก Log Files
php_flag, php_value
คือ การปรับแต่ง php เป็นพิเศษสำหรับ server ตัวนี้เท่านั้น
DocumentRoot
คือ folder ที่ไว้เก็บ php ที่เราตั้งใจแยกไว้ เป็น code ชุดเดียวกับที่เราจะเอาขึ้น server จริง
ServerAdmin, ServerName
คือ ข้อมูล server แต่ละตัว

ทดสอบโดย restart apache ใหม่และเปิดเว็บ

จัดระเบียบเซิร์ฟเวอร์

ในครั้งแรกที่เราเรียนเขียนเว็บจะถูกสอนให้เก็บไฟล์ ในโฟลเดอร์ public_html หรือ www เพื่อจะได้เรียกใช้ได้จากเว็บ พอเว็บเราโตขึ้นมันทำให้สับสน และมีปัญหาตามมา เช่น

  1. จากที่อาจจะมีแค่ joomla อยู่อย่างเดียว ก็จะใส่ phpbb เพิ่มเข้าไป ถ้าไม่ย้ายไฟล์ joomla ไปไว้ใน folder ย่อย ก็ต้องใส่ phpbb ไปใน folder ย่อยเวลาจะเรียกใช้ก็เรียก domain1.com/phpbb  ถ้าไม่ถูกใจ phpMyAdmin ตัวเก่าๆที่ติดมากับโฮสต์ จะใช้ตัวใหม่ก็สร้าง folder phpMyAdmin ขึ้นมา ไปเรื่อยๆ แล้วมันจะมีปัญหาอะไรละ
    • ถ้าจะเปลี่ยนจากจูมล่าเป็น wordpress ก็ต้องมาหาว่า folder นี้เป็นของ joomla นะ ต้องดูให้แน่ใจว่ามันไม่ถูกใช้โดยโป��แกรมอ��่น จะท���้งไว้ก็เสียพื้นที่ไปเปล่าๆ
    • การ update อัตโนมัติของบางโปรแกรมอย่าง prestashop ให้วิธีลบทั้งโฟลเดอร์ออกไปทั้งหมด แล้วแตกไฟล์เข้าไปใหม่ ถ้าใน folder นั้นๆ มีไฟล์ของโปรแกรมอื่นละ มันก็ล่มโดยที่เราไม่รู้ตัว
    • บางครั้งโปรแกรมต้องใช้การ config ที่ต่างกัน อย่าง joomla จะเตือนถ้าพบว่า magic_quotes_gpc  เปิดอยู่ แต่โปรแกรมโบราณต้องเปิดไว้ ถ้าเราก็บแยกโพลเดอร์ก็สามารถใช้ .htaccess เปิดปิดได้ตามความต้องการ
  2. จะสร้างเว็บใหม่ ใช้ joomla เหมือนกัน ไว้ที่เดียวกัน บางครั้งสับสน ว่าโพลเดอร์นี้ เป็นของโดเมนไหน

ถ้าเราเก็บไฟล์โดยใช้รูปแบบ public_html/domain1.com, public_html/domain2.com, public_html/ domain3.com ก็จะแก้ปัญหาข้อ 2 ได้

ในแต่ละ domain ก็แบ่งย่อยเป็น joomla, phpbb อีก ให้โปรแกรมแต่ละตัวแยกอิสระต่อกัน

แต่ การที่จะให้ผู้ใช้ลูกค้าของเราดูเว็บ แบบ http://domain1.com/domain1.com/Joomla คงไม่ดีแน่ ทั้งในเรื่องความสะดวกและ SEO เราสามารถใช้ ไฟล์ .htaccess  point ชี้ root diretory ให้เราใหม่

  1. เปิดไฟล์ .htaccess ในโฟลเดอร์ public_html  ถ้าไม่มี ก็สามารถสร้างขึ้นมาใหม่ได้ ด้วย โปรแกรม notepad แล้ว save เป็นชื่อ .htaccess ตรง Save As Type เลือกเป็น All Files (*.*)
  2. พิมพ์ ตามตัวอย่างเลยครับ[sourcecode langlage=”text”]
    # BlueHost.com
    # .htaccess main domain to subdirectory redirect
    # Do not change this line.
    RewriteEngine on
    # Change example.com to be your main domain.
    RewriteCond %{HTTP_HOST} ^(www.)?example.com$
    # Change ‘subdirectory’ to be the directory you will use for your main domain.
    RewriteCond %{REQUEST_URI} !^/subdirectory/
    # Don’t change the following two lines.
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    # Change ‘subdirectory’ to be the directory you will use for your main domain.
    RewriteRule ^(.*)$ /subdirectory/$1
    # Change example.com to be your main domain again.
    # Change ‘subdirectory’ to be the directory you will use for your main domain
    # followed by / then the main file for your site, index.php, index.html, etc.
    RewriteCond %{HTTP_HOST} ^(www.)?example.com$
    RewriteRule ^(/)?$ subdirectory/index.html [L]
    [/sourcecode] copy คู่มือของเซิร์ฟเวอร์มานั่นละ แต่กลัวลืมเลยขอ note ไว้หน่อยหนึ่ง
  3. แก้ example.com เป็น domain ของเรา แก้ subdirectory เป็นโฟลเดอร์ของเรา
  4. ทดลองเข้า โดเมน domain ของเรา จะพบว่าเราเห็นไฟล์ในโฟลเดอร์ subdirectory อีกชั้นหนึ่งไม่ใช่ ตัว public_html

ปิด magic_quotes ด้วย htaccess

Joomla 3 จะมีปัญหาภาพไม่ขี้น ไม่สามารถติดตั้งได้ เพราะว่าเปิด magic_quotes_gpc ไว้ ถ้าเราไม่สามารถปิด ใน php.ini ได้ (เช่าแชร์เซิร์ฟเวอร์เค้าใช้ต้องทำใจ) หรือมีโปรแกรมโบราณสมัยพระเจ้าหลุยส์ที่สิบสามอยู่ด้วย ทำให้ปิดไม่ได้ เราก็สามารถทำได้ด้วยไฟล์ .htaccess

  1. เปิดไฟล์ .htaccess ในโฟลเดอร์ที่เก็บไฟล์จูมล่าไว้ ถ้าไม่มี ก็สามารถสร้างขึ้นมาใหม่ได้ ด้วย โปรแกรม notepad แล้ว save เป็นชื่อ .htaccess ตรง Save As Type เลือกเป็น All Files (*.*)
  2. พิมพ์
    [sourcecode language=”text”]
    # disabel magic_quotes for joomla
    php_flag magic_quotes off
    php_flag magic_quotes_gpc off
    php_value magic_quotes 0
    php_value magic_quotes_gpc 0
    [/sourcecode]