Tag Archive server

Byphunsanit

เซ็ต 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 เท่านั้นเอง ง่ายจริงๆ

Byphunsanit

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 ซับซ้อนกว่านี้เพื่อความปลอดภัย

Byphunsanit

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

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

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

  • จะส่ง token มาและทั้ง 2 ไฟล์จะต้องมีค่าเท่าๆกัน ในความเป็นจริง ควรจะมีการเขียนที่ดีกว่านี้ เช่น เปลี่ยน token ตามช่วงเวลา
  • ไม่ควรให้ร้องขอไฟล์โดยใช้ full path และเพื่อป้องกันการใช้ฝั่งรับในการ download ไฟล์อื่นๆ จึงต้องกำหนดโฟลเดอร์เริ่มต้นไว้ให้ดาวน์โหลดไฟล์ในโฟลเดอร์ที่กำหนดไว้เท่านั้น
  • <?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);

    <?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');
    }
    

Byphunsanit

curl: ส่งไฟล์

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

<!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>

แต่เพราะ bug ของ function http_build_query ไม่สามารถ encoded query string ในกรณีที่มีไฟล์ได้อย่างถูกต้อง ทำให้ต้องส่งค่าฟอร์มไปโดยไม่เข้ารหัส ดังนั้น ค่าที่เป็น array จึงส่งค่าออกไปผิด

[address]Array
(
    [name] => pitt phunsanit
    [address] => Array
)

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

Byphunsanit

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

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

<!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>

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