andy0130tw
7/9/2014 - 9:18 AM

CRSC2014 Guestbook Backend

CRSC2014 Guestbook Backend

The backend of CRSC2014 guestbook for Yu-Ren Pan! Using PHP(>5.3), SQLite3. With a little tweak, you can use PDO to rewrite it so that you can run it in PHP 5.1.

By Andy Pan H1296. Have fun!

<?php
  //Comment for easier reading
   
  // Override default SQLite constructor to
  // open the file at first.
  class MyDB extends SQLite3{
    function __construct(){
      $this->open('dbstore/gb.sqlite');
    }
  }
  
  //Email regex for validation
  $regex_email="/^[a-z0-9!#$%&'*+\\/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+\\/=?^_`{|}~-]+)*"
    ."@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i";
  
  //Auth!
  //You can arbitally set this value
  // but do not expose it
  $PASS_SALT="madebyandy1296";
  //The most important part! The password
  // shown is 'banana' 
  $PASS_SHA1="198df1ceb81e0f70943b0da0fcf68f2b845b060a";

  $isAdmin=isset($_POST["pass"])&&sha1($_POST["pass"].$PASS_SALT)===$PASS_SHA1;

  function normalizeNL($str){
    return preg_replace("/\R/u", "\n", $str);
  }

  function makeFlaggedMessage($data){
    return array(
      "no"=>$data["no"],
      "flagged"=>true,
      "comment"=>"管理員已經刪除此訊息!",
      "timestamp"=>$data["timestamp"]
    );
  }

  //Send header so that the content will be recognized as JSON.
  header( 'Content-type: application/json' );
  $db = new MyDB();
  $action=$_GET["action"];    

  function writeData(){
    global $db,$data,$regex_email,$info,$isAdmin;

    //Truncate the incoming data
    $_POST["name"]=substr($_POST["name"],0,24);
    $_POST["comment"]=substr($_POST["comment"],0,1024);
    //normalize newline characters
    $_POST["comment"]=normalizeNL($_POST["comment"]);

    $stmt=$db->prepare("insert into book (`category`,`name`,`email`,`comment`,`related`,`by_admin`)"
      ." values (?,?,?,?,?,?)");
    
    if(!$_POST["name"]||!$_POST["comment"])
      return "Some parameters are missing!";

    if($_POST["email"]){
      $vali=preg_match($regex_email,$_POST["email"]);
      if($vali===0){
        return "Email is not valid!";
      }else if(!$vali){
        return "Error occured while validating email.";
      }
    }

    if($_POST["related"]){
      $stmt_count=$db->prepare("select category from book where no=?");
      $stmt_count->bindParam(1,$_POST["related"],SQLITE3_TEXT);
      $relcat=$stmt_count->execute()->fetchArray(SQLITE3_NUM);
      if(!$relcat)
        return "Related post does not exist.";
      else if($relcat[0]=="reply")
        return "Nested replies are banned.";
    }

    $cat=$_POST["related"]?"reply":"comment";
    $byAdmin=$isAdmin?1:NULL;
    if($byAdmin)
      $info["by_admin"]=true;

    //bind param as follows
    $stmt->bindParam(1,$cat,SQLITE3_TEXT);
    $stmt->bindParam(2,$_POST["name"],SQLITE3_TEXT);
    $stmt->bindParam(3,$_POST["email"],SQLITE3_TEXT);
    $stmt->bindParam(4,$_POST["comment"],SQLITE3_TEXT);
    $stmt->bindParam(5,$_POST["related"],SQLITE3_TEXT);
    $stmt->bindParam(6,$byAdmin,SQLITE3_INTEGER);
    
    //id and timestamp will automatically be added,
    // so we don't need to worry about them.
    $stmt->execute();
    return false;
  }
   
  $et=microtime(true);

  //array works like dict in python
  $rtn=array();
  $info=array();
  $data=array();
 
  if($action=="write"){
    $result=writeData();
    if(!$result){
      $rtn["status"]="ok";
      $rtn["msg"]="Data is successfully saved.";
    }else{
      $rtn["status"]="error";
      $rtn["msg"]=$result;
    }
    
  }else if($action=="read"){
    $info["status"]="ok";
    $result=$db->query("select `no`,`name`, `flagged`, `email`, `comment`, `by_admin`, datetime(`timestamp`,'+8 hours') as `timestamp` from book order by `no` desc");
    while($arr=$result->fetchArray(SQLITE3_ASSOC)){
      $arr["comment"]=normalizeNL($arr["comment"]);
      $data[]=$arr["flagged"]?makeFlaggedMessage($arr):$arr;
      //must ensure that the related data does exist!!!!
    }
  }else if($action=="hide"){
    if(!$isAdmin){
      $rtn["status"]="error";
      $rtn["msg"]="Auth failed. This can only be done by administrators.";
    }else{
      $stmt=$db->prepare("update book set `flagged`= (`flagged` is null or(not `flagged`)) where no=?");
      if(isset($_POST["comment"])){
        $stmt->bindParam(1,$_POST["comment"],SQLITE3_TEXT);
        $stmt->execute();
        if($affect_rows=$db->changes()){
          $rtn["status"]="ok";
          $info["affect_rows"]=$affect_rows;
        }else{
          $rtn["status"]="error";
          $rtn["msg"]="No record found.";
        }
      }else{
        $rtn["status"]="error";
        $rtn["msg"]="Invalid parameters.";
      }
    }
  }else{
    //not supported action
    $rtn["status"]="error";
    $rtn["msg"]="Specified action is not supported!";
  }
  $info["elapsed-time"]=round((microtime(true)-$et)*1000,3);
 
  $rtn["info"]=$info;
  $rtn["data"]=$data;
 
  print json_encode($rtn);
  //Do not leave anything beyond the end of the tag!
?>