2018年12月25日 星期二

【apache】VC6 9 11 15?

安裝apache到windows有分VC多少版本的
他是指用VisualStudio多少版本編譯的,windows也要去下載對應套件才能用
但太舊的windows會不支援新版的VisualStudio

VC6 Visual Studio 6
VC9 Visual Studio2008
VC11 Visual Studio2012 (xp、windows server2003不支援)
VC14 Visual Studio2015 (xp、windows server2003不支援)
VC15 Visual Studio2017 (xp、windows server2003不支援)

【PHP】php.ini 設定發信信箱及信箱密碼 win32

參考網址:http://php.net/manual/en/ref.mail.php

1.到 http://glob.com.au/sendmail/ 下載 sendmail

2.找個目錄放,我是放到跟php的目錄裡面

3.修改php.ini 找到 mail function 
    修改 sendmail_path = "C:\php\sendmail\sendmail.exe -t" (剛剛下載的檔案的位置)

4.修改 sendmail 裡的 sendmail/sendmail.ini
    smtp_server=(郵件主機)
    auth_username=(帳號)
    auth_password=(密碼)

2018年12月10日 星期一

【CSS】mask 滿畫面

  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background-color: #000;
  opacity: 0.65;
  z-index: 100;

2018年9月7日 星期五

【PHP】瀏覽過的商品

function save_history($id,$max=10)
{
 $t = 60 * 60 * 24 * 365;
 if ($_COOKIE['history_goods'])
 {
  $history_goods_arr = json_decode($_COOKIE['history_goods'],true);
  if (in_array($id,$history_goods_arr))
  {
   return false;
  }
  if (count($history_goods_arr) >= $max)
  {
   array_shift($history_goods_arr);
  }
  $history_goods_arr[] = $id;

  setcookie("history_goods",'',time()-3600);
  setcookie("history_goods",$history_goods,time()+$t);

 } else {
  $history_goods_arr[] = $id;
  $history_goods = json_encode($history_goods_arr);
  setcookie("history_goods",$history_goods,time()+$t);
 }

}

2018年8月17日 星期五

【PHP】extract

extract 這很好用可以直接把陣列變成變數

$my_array = array("a" => "Cat","b" => "Dog", "c" => "Horse");
extract($my_array);
echo "\$a = $a; \$b = $b; \$c = $c";

但不要用於GET和POST

【PHP】htmlspecialchars && htmlentities && urlencode

htmlspecialchars 與 htmlentities 感覺效果一樣都是把HTML的標籤變成代碼

但 htmlspecialchars 只會轉換特定的符號,htmlentities 轉換的比較多

所以一般要用 htmlspecialchars 速度較快

urlencode 主要是編碼 URL

【PHP】serialize && json

有天看到資料別人資料出現:a:2:{i:0;s:1:"1";i:1;s:1:"2";}

這是三小,

後來查一下他是用 serialize 將 array 編碼後的字串,

我一般都是用 json_encode 將陣列編碼在存入資料庫,

查了一下 serialize 好處是可以把整個class轉成字串,

但一般沒特殊需求還是用 JSON 格式,不但可讀也可跨平台。


2018年7月2日 星期一

【Google】AMP 行動網站加速計劃

Accelerated Mobile Pages (AMP) 是一種根據開放原始碼規格所設計的網頁。
透過 AMP 製作技術,您能夠大大縮短靜態內容的渲染時間從而有效提升網頁效能。
缺點是限制很多

官方網頁
AMP測試

2018年6月29日 星期五

【PHP】判斷連結圖片是否存在,如果不存在將他移除

// 建立白名單
require_once('../class/htmlpurifier/HTMLPurifier.auto.php');
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML', 'Allowed', 
'
,area[accesskey|alt, coords|href|name|shape|tabindex|target]
,img[alt|border|height|ismap|src|usemap|width]
,b,blockquote[cite],br,dd,dl,dt,em,h1,h2,h3,h4,h5,h6
,hr,i,li[value],map,ol[start|type]
,nav[accesskey|contenteditable|contextmenu|data-*|draggable|dropzone|hidden|spellcheck|tabindex|translate]
,ol[start|type],p,pre,rp,rt,ruby,s,small,source,strike,strong,style,sub,sup,
,table[border|cols|summary|cellpadding|cellspacing|align]
,tbody[valign],td[bordercolor|colspan|rowspan],tfoot[valign]
,th[colspan|rowspan|scope],thead[valign],tr[colspan|rowspan]
,tt,u,ul,video[autoplay|controls|height|loop|muted|poster|preload|src|width]
,div[style|class|id]
,span[style|class|id]
'
);

$purifier = new HTMLPurifier($config);
$rs['description'] = $purifier->purify($rs['description']);


// 判斷連結圖片是否存在,如果不存在將他移除
preg_match_all("//", $rs['description'], $img_arr);

if ($img_arr)
{

 foreach($img_arr[1] as $key=>$img)
 {
  $size_arr = getimagesize($img);

  if (!$size_arr)
  {
   $img_arr[0][$key];
   $rs['description'] = str_replace($img_arr[0][$key], '', $rs['description']);
  }
 }
}

2018年6月28日 星期四

【PHP】addslashes & stripslashes 符號前加斜線

常常忘了這兩個函數 addslashes、stripslashes

$str = "Is your name O'reilly?";

// 輸出:Is your name O\'reilly?
$str = addslashes($str);
echo $str;

echo stripslashes($str);

【PHP】簡易mail發送

// 寄信 email可用逗點分隔一次寄給多人
function send_mail($subject, $content, $email, $cc=array()){
 $charset = 'utf-8';
 $sitename = PROJECT_NAME;
 $ADM_EMAIL = ADM_EMAIL;
 $encoded_subject = mail_header_encode($subject,$charset);
 $sitename2 = mail_header_encode($sitename,$charset);  
 
 $headers = "From: ".$sitename2 ."<".$ADM_EMAIL.">". "\r\n";
 $headers .= "Content-Type: text/html; charset=$charset; format=flowed". "\r\n";
 $headers .= "MIME-Version: 1.0". "\r\n";
 $headers .= "Content-Transfer-Encoding: 8bit". "\r\n";
 $headers .= "X-Mailer: PHP". "\r\n";
 
 if ($cc){
  foreach($cc as $mail){
   $headers .= "Cc: $mail" . "\r\n";
  }
 }
 
 $r = mail($email, $encoded_subject, $content, $headers);
 return $r;
}

// 寄信用的編碼
function mail_header_encode($str,$charsets){
 return "=?$charsets?B?".base64_encode($str)."?=";
}

【jquery】插入內容方式

久沒用就會忘記,快點記下來
after()
before()
insertAfter()
insertBefore()
prepend()
prependTo()
append()
appendto()

2018年6月27日 星期三

【javascript】framework

javascript framework 流行的有 vue、react、angular
我覺得用jquery就很好用了

2018年6月26日 星期二

【Redis】什麼是 Redis?

Redis 是一種快速、開放原始碼的記憶體內鍵值資料結構存放區。
Redis 隨附一組多功能的記憶體內資料結構,讓您能夠輕鬆地建立各種自訂應用程式

與資料存放在磁碟或 SSD 的大多數資料庫管理系統不同,
所有 Redis 資料都位於自己的伺服器主記憶體。
因為不需要存取磁碟,像 Redis 這樣的記憶體內資料庫可避免尋找時間延遲,
還可以透過使用較少 CPU 指示的較簡單演算法存取資料。
通常操作都可在一毫秒內完成。

大流量的處理適合使用

https://aws.amazon.com/tw/elasticache/what-is-redis/

https://www.ithome.com.tw/news/119974

【PHP】為什麼大家不用 Session 了?

1.負載平衡 Session不好處理,用token後台可以支援多個平台(web、APP)
2.防止跨網域請求偽造攻擊(CSRF),每次請求都要先獲得token,只有連結不能執行

產生 token
https://blog.7311.tw/2013/12/php-token.html

https://yami.io/jwt/

【jquery】bind、live、on

bind必需要每一個HtmlElement都要綁定,而live不用,
live適合用在動態新增element,如Ajax下載回來的HTML,
用live其中相同的selector的HtmlElement,就不用重Bind,
可以省去不少麻煩。

//在 jQuery 1.3 以上版本
$(selector).live(events, data, handler);
//在 jQuery 1.4.3 以上版本
$(document).delegate(selector, events, data, handler);
//在 jQuery 1.7 以上版本
$(document).on(events, selector, data, handler);

$(":input").bind("keyup change", function(e) {
    // do stuff!
})
 $("#myform").on("change","input",save_complete);
 $("#myform").on("change","select",save_complete);
 $("#myform").on("click",".del_score",del_score);


https://dotblogs.com.tw/wadehuang36/2010/10/13/jquery-bind-live

【javascript】event.preventDefault() 與 event.stopPropagation()

javascript 要停止執行程式可以用 event.preventDefault() 與 event.stopPropagation()

stopPropagation 可阻止冒泡事件發生

差別:https://dotblogs.com.tw/harry/2016/09/10/131956
https://www.cnblogs.com/jiqing9006/archive/2012/09/11/2679831.html

2018年6月25日 星期一

【AnyDesk】鍵盤設置

如果要用AnyDesk寫程式,
記得要把【設定】裡面的【系統轉換按鍵】取消!!



【Bootstrap】CSS3 icon 圖示

做網頁常常要用到小icon,以前都是用image,
現在可以直接用更方便的bootstrap的css的icon,

https://www.w3schools.com/icons/bootstrap_icons_glyphicons.asp

2018年6月13日 星期三

【HTML5】Google 網頁設計師

Google 發布的HTML5編輯器,圖形化介面可以快速產生HTML5動畫

有空來玩玩

網址:https://www.google.com/webdesigner/

【PHP】HTML直接輸出PDF

可以使用 tcpdf
網址:https://tcpdf.org/
範例:https://tcpdf.org/examples/example_021/

require("class/TCPDF-master/tcpdf.php");
class Mya_tcpdf 
{
 
 public function tcpdf_html($html, $title)
 { 
  // create new PDF document
  $pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
  
  // set document information
  $pdf->SetCreator(PDF_CREATOR);
  $pdf->SetAuthor('');
  $pdf->SetTitle($title);
  $pdf->SetSubject('');
  $pdf->SetKeywords('');
  
  // set default header data
  $pdf->setPrintHeader(false);
  $pdf->setFooterFont(array(PDF_FONT_NAME_DATA, '', 10));
  
  // set default monospaced font
  $pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
  
  // set margins
  //$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
  $pdf->SetMargins(10, 10, 10);
  $pdf->SetHeaderMargin(0);
  $pdf->SetFooterMargin(10);
  
  // set auto page breaks
  $pdf->SetAutoPageBreak(TRUE, 10);
  
  // set image scale factor
  $pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
  
  // set some language-dependent strings (optional)
  if (@file_exists(dirname(__FILE__).'/lang/eng.php')) {
   require_once(dirname(__FILE__).'/lang/eng.php');
   $pdf->setLanguageArray($l);
  }   
  
  // set font
  $pdf->SetFont('msjh','',1); // 字形需另外下載

  // add a page
  $pdf->AddPage();

  // output the HTML content
  $pdf->writeHTML($html, true, false, true, false, '');

  // reset pointer to the last page
  $pdf->lastPage();

  // ---------------------------------------------------------

  //Close and output PDF document
  $pdf->Output("abc.pdf", 'I');
 } 
 
}

【PHP】HTML Purifier 可過濾HTML限定只能用那些HTML

碰到只能用某些HTML,自己過濾超麻煩,

























後來找到好用的套件 :HTML Purifier

裡面還有很多功能,也可阻擋XSS攻擊

require('class/htmlpurifier/HTMLPurifier.auto.php');

$config = HTMLPurifier_Config::createDefault();


$config->set('HTML', 'Allowed', 
 'a[accesskey|href|rel|tabindex}target|type]
 ,area[accesskey|alt, coords|href|name|shape|tabindex|target]
 ,img[alt|border|height|ismap|src|usemap|width]
 ,b,blockquote[cite],br,dd,div,dl,dt,em,h1,h2,h3,h4,h5,h6
 ,hr,i,li[value],map,ol[start|type]
 ,nav[accesskey|contenteditable|contextmenu|data-*|draggable|dropzone|hidden|spellcheck|tabindex|translate]
 ,ol[start|type],p,pre,rp,rt,ruby,s,small,source,span,strike,strong,style,sub,sup,
 ,table[border|cols|summary|cellpadding|cellspacing|align]
 ,tbody[valign],td[bordercolor|colspan|rowspan],tfoot[valign]
 ,th[colspan|rowspan|scope],thead[valign],tr[colspan|rowspan]
 ,tt,u,ul,video[autoplay|controls|height|loop|muted|poster|preload|src|width]
 '
 );
$purifier = new HTMLPurifier($config);
echo $cleanContent = $purifier->purify($content);

2018年6月7日 星期四

【Jquery UI】拖移(sortable)抓到值

$(".cat1 .type-sort").sortable({update: function (e, ui){
    $current_id = ui.item.attr('id');
    $change_id = ui.item.prev().attr('id');
    console.log(ui.item.attr('id')+'/'+ui.item.prev().attr('id'));

    console.log($("#"+$current_id).html());
  }});

【Jquery】動態產生也可綁定事件

利用Jquery產生出來的物件 (append、prepend),
在之前設定的$('.item').click()會失效,
要改成 $('body').on('click','.item',funciton (){});

2018年5月29日 星期二

【PHP】JSON 相關

1.編碼 JSON 時保留 key 值

$post_data = json_encode(array('aaa'), JSON_FORCE_OBJECT);
// 輸出  {"0":"aaa"}

2.解碼時用陣列

$array = json_decode($json, true);
echo $array['foo'] . PHP_EOL; //"bar"
echo $array['number'] . PHP_EOL; //42

3.陣列轉換成物件 {}

$obj = (object) array('1' => 'foo');
$a = new stdclass; $a->id = 11;

4.sublime prettify 的快捷鍵是 Ctrl + Alt + J (要先安裝)


【PHP】型態轉成object

有時要把型態轉成object可用

方法一: $obj = (object) array('1' => 'foo');

方法二:$a = new stdclass; $a->abc = 'abc';

目前有用到的時機

1.轉json時,為了符合別人定的API的JSON規則,需要轉成object

2.建立一個空的類只是為了傳遞或儲存參數時

2018年5月28日 星期一

【PHP】XML to array

/** 
 * xml2array() will convert the given XML text to an array in the XML structure. 
 * Link: http://www.bin-co.com/php/scripts/xml2array/ 
 * Arguments : $contents - The XML text 
 *                $get_attributes - 1 or 0. If this is 1 the function will get the attributes as well as the tag values - this results in a different array structure in the return value.
 *                $priority - Can be 'tag' or 'attribute'. This will change the way the resulting array sturcture. For 'tag', the tags are given more importance.
 * Return: The parsed XML in an array form. Use print_r() to see the resulting array structure.
 * Examples: $array =  xml2array(file_get_contents('feed.xml')); 
 *              $array =  xml2array(file_get_contents('feed.xml', 1, 'attribute')); 
 */ 
function xml2array($contents, $get_attributes=1, $priority = 'tag') { 
    if(!$contents) return array(); 

    if(!function_exists('xml_parser_create')) { 
        //print "'xml_parser_create()' function not found!"; 
        return array(); 
    } 

    //Get the XML parser of PHP - PHP must have this module for the parser to work 
    $parser = xml_parser_create(''); 
    xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, "UTF-8"); # http://minutillo.com/steve/weblog/2004/6/17/php-xml-and-character-encodings-a-tale-of-sadness-rage-and-data-loss 
    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); 
    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); 
    xml_parse_into_struct($parser, trim($contents), $xml_values); 
    xml_parser_free($parser); 

    if(!$xml_values) return;//Hmm... 

    //Initializations 
    $xml_array = array(); 
    $parents = array(); 
    $opened_tags = array(); 
    $arr = array(); 

    $current = &$xml_array; //Refference 

    //Go through the tags. 
    $repeated_tag_index = array();//Multiple tags with same name will be turned into an array
    foreach($xml_values as $data) { 
        unset($attributes,$value);//Remove existing values, or there will be trouble 

        //This command will extract these variables into the foreach scope 
        // tag(string), type(string), level(int), attributes(array). 
        extract($data);//We could use the array by itself, but this cooler. 

        $result = array(); 
        $attributes_data = array(); 
         
        if(isset($value)) { 
            if($priority == 'tag') $result = $value; 
            else $result['value'] = $value; //Put the value in a assoc array if we are in the 'Attribute' mode
        } 

        //Set the attributes too. 
        if(isset($attributes) and $get_attributes) { 
            foreach($attributes as $attr => $val) { 
                if($priority == 'tag') $attributes_data[$attr] = $val; 
                else $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr' 
            } 
        } 

        //See tag status and do the needed. 
        if($type == "open") {//The starting of the tag '' 
            $parent[$level-1] = &$current; 
            if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
                $current[$tag] = $result; 
                if($attributes_data) $current[$tag. '_attr'] = $attributes_data; 
                $repeated_tag_index[$tag.'_'.$level] = 1; 

                $current = &$current[$tag]; 

            } else { //There was another element with the same tag name 

                if(isset($current[$tag][0])) {//If there is a 0th element it is already an array 
                    $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result; 
                    $repeated_tag_index[$tag.'_'.$level]++; 
                } else {//This section will make the value an array if multiple tags with the same name appear together
                    $current[$tag] = array($current[$tag],$result);//This will combine the existing item and the new item together to make an array
                    $repeated_tag_index[$tag.'_'.$level] = 2; 
                     
                    if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
                        $current[$tag]['0_attr'] = $current[$tag.'_attr']; 
                        unset($current[$tag.'_attr']); 
                    } 

                } 
                $last_item_index = $repeated_tag_index[$tag.'_'.$level]-1; 
                $current = &$current[$tag][$last_item_index]; 
            } 

        } elseif($type == "complete") { //Tags that ends in 1 line '' 
            //See if the key is already taken. 
            if(!isset($current[$tag])) { //New Key 
                $current[$tag] = $result; 
                $repeated_tag_index[$tag.'_'.$level] = 1; 
                if($priority == 'tag' and $attributes_data) $current[$tag. '_attr'] = $attributes_data;

            } else { //If taken, put all things inside a list(array) 
                if(isset($current[$tag][0]) and is_array($current[$tag])) {//If it is already an array... 

                    // ...push the new element into that array. 
                    $current[$tag][$repeated_tag_index[$tag.'_'.$level]] = $result; 
                     
                    if($priority == 'tag' and $get_attributes and $attributes_data) { 
                        $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data; 
                    } 
                    $repeated_tag_index[$tag.'_'.$level]++; 

                } else { //If it is not an array... 
                    $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
                    $repeated_tag_index[$tag.'_'.$level] = 1; 
                    if($priority == 'tag' and $get_attributes) { 
                        if(isset($current[$tag.'_attr'])) { //The attribute of the last(0th) tag must be moved as well
                             
                            $current[$tag]['0_attr'] = $current[$tag.'_attr']; 
                            unset($current[$tag.'_attr']); 
                        } 
                         
                        if($attributes_data) { 
                            $current[$tag][$repeated_tag_index[$tag.'_'.$level] . '_attr'] = $attributes_data; 
                        } 
                    } 
                    $repeated_tag_index[$tag.'_'.$level]++; //0 and 1 index is already taken 
                } 
            } 

        } elseif($type == 'close') { //End of tag '' 
            $current = &$parent[$level-1]; 
        } 
    } 
     
    return($xml_array); 
}  

2018年5月25日 星期五

【PHP】UUID

串接API時常常會發現很多亂碼,

類似:570e8400-e29b-41d4-a716-44b6594400a0

以為是每個廠商為了辨別所創立的亂數,

原來它有一定的格式及名稱

通用唯一識別碼(英語:Universally Unique Identifier,簡稱UUID)

形式為8-4-4-4-12的32個字元,重複率超低,

所以每次產生都能當作此筆交易或是交換的唯一值


function create_uuid($prefix = ""){
    $str = md5(uniqid(mt_rand(), true));  
    $uuid  = substr($str,0,8) . '-';  
    $uuid .= substr($str,8,4) . '-';  
    $uuid .= substr($str,12,4) . '-';  
    $uuid .= substr($str,16,4) . '-';  
    $uuid .= substr($str,20,12);  
    return $prefix . $uuid;
} 

【PHP】php實現 AES/CBC/PKCS5Padding 加密解密

最近在做一個API串接,對方是用JAVA寫的,

中間有要編碼的片段,編碼方式是AES (CBC模式) 轉 Base64,

我上網找了用下面方法加解密,
$encrypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $app_cc_aes_key, $data, MCRYPT_MODE_CBC, $app_cc_aes_iv);

用此方法可以順利解密,但是編碼後對方怎麼樣都解不開,

來回溝通搞了好久,上網爬文好久終於才找到解決方法,

原來是補碼的方式不同PHP是用ZeroPadding,JAVA是用PKCS5Padding,

※ 在PHP官網寫說關於mcrypt的function,PHP7.1之後不能使用!!

class AES {
 public $iv;

 public $encryptKey;

 //加密
 public function encrypt($encryptStr) {
  $localIV = $this->iv;
  $encryptKey = $this->encryptKey;

  $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, $localIV);

  mcrypt_generic_init($module, $encryptKey, $localIV);

  $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
  $pad = $block - (strlen($encryptStr) % $block); 
  $encryptStr .= str_repeat(chr($pad), $pad); 

  $encrypted = mcrypt_generic($module, $encryptStr);

  mcrypt_generic_deinit($module);
  mcrypt_module_close($module);

  return base64_encode($encrypted);
 }

 //解密
 public function decrypt($encryptStr) {
  $localIV = $this->iv;
  $encryptKey = $this->encryptKey;

  $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, $localIV);

  mcrypt_generic_init($module, $encryptKey, $localIV);

  $encryptedData = base64_decode($encryptStr);
  $encryptedData = mdecrypt_generic($module, $encryptedData);

  return $encryptedData;
 }
}