星期日, 1月 29, 2012

亂數order id

最近在寫銷售系統,由於會把order id給客戶,主管反應這樣會被會看出銷售量,所以要改成亂數,避免競爭對手等看出銷售數量。

研究了半天,自己用padding、加亂數的方法似乎還是會被察覺,google後,覺得還是用加密比較簡單

  • two way encryption
    先下載加密法encryption_class.php
    在encryption_class.php裡,有以下兩行
    $this->scramble1 = '! #$%&()*+,-./0123456789:;>=<?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~';
    $this->scramble2 = 'f^jAE]okIOzU[2&q1{3`h5w_794p@6s8?BgP<dFV=m D>TcS%Ze|r:lGK/uCy.Jx)HiQ!#$~(;Lt-R}Ma,NvW+Ynb*0X';
    此加密法是簡單的利用代換字母做加密,記得叫Caesar Cipher什麼的,主要利用自己的key,去對應scramble相同字母的位置
    當然這樣1對1的對應,很容易就被破,所以裡面的function _applyFudgeFactor(),就是在每次計算代換字母就偏移順序
    利用scramble1把key轉換成順序,每次再偏移位置,從scramble2取出該字母當祕文
  • 產生加密後的order id
    <?php
    include 'encryption_class.php';
    
    $crypt = new encryption_class(); 
    
    $key = "A-COMPLETELY-RANDOM-KEY-THAT-I-HAVE-USED";
    // Min length of 8 for encrypted string
    $min_length = 8;
    
    $order_id = 123456789;
    
    print "Original: " . $order_id . PHP_EOL;
    
    $encrypt_result = $crypt->encrypt($key, $order_id, $min_length); 
    
    print "Encrypted: " . $encrypt_result . PHP_EOL;
    
    // DECRYPT
    $decrypt_result = $crypt->decrypt($key, $encrypt_result);
    
    print "Decrypted: " . $decrypt_result . PHP_EOL;
    
    ?>
    結果如下
    Original: 123456789
    Encrypted: 2UD5UIK9S
    Decrypted: 123456789

  • 以數字實作
    不過問題又來了,因為order id用integer,所以要求全是數字
    • 轉ascii code
      就直接全轉3位數的ascii code

      $numeric_cipher='';
      for($i=0;$i<strlen($decrypt_result);$i++){
          $numeric_cipher .= str_pad(ord(substr($decrypt_result,$i,1)),3,'0',STR_PAD_LEFT); //不到3碼,左邊補0至3碼
      }
      

      不過實在太長了,5位數就要長到15個數字
      所以ascii百位數後全不用,即d(100),e(101),...
      這樣padding就只要2位,這樣5位數也只要10個數字
    • 還嫌太長!?最終極版大絕!!!
      由於key是對應scremble的排序...
      把key跟scremble都只放數字,這樣............ 應該夠短了吧...
      就是有點容易猜...不過一時間內應該也夠用了
      order id太長,將來要查也不好查
      • 改encryption_class.php
        //把scramble改成如下,不要重覆,順序可亂擺,不要一樣就好
        $this->scramble1 = '0123456789';
        $this->scramble2 = '2135794680';
      • 改key值
        因為要對應scramble,所以key有什麼值,scramble就要有什麼值,否則對應不到
        至於密文min length長度,當超過明文長度時,預設是在字串後方補上空格
        但因為得全為數字,所以scramble沒有空格,造成空格對應不到,因此不能超過order id的長度

        //key可隨意變化,但key的值一定要出現在scramble裡
        $key='1234534567890';   
        $key='11223344';   
        $key='68490';   
        
        $min_length = strlen($order_id); //因為1對1,所以不能超過order id的長度
        
      結果如下
      OriginalEncryptedDecrypted
      151
      70
      115011
      991999
      100583100
      101585101
      110505110
      111507111
      這就可以看出來,當key、scramble、偏移量相同,位於前面的字母相同時,代碼都會相同,變化不夠大,忘了那資安的名詞叫什麼,意思是當原文變化不大時,密文的變化仍要夠大,如md5等
      因為可變化的太少了,不過應該算堪用了
      另外還有兩個問題
      • original為7時,沒辦法反解
        原作者在decrypt用empty,所以遇到0會當false,改!isset即可
        相同的,當encrypt 0時,也會當成false,也需要改成!isset
      • decrypt result為0xx
        雖是正常,不過ordre id用integer,這個0就會不見,到時會解不回去
      min length問題
      由於是全數字,又密文長度不能超過明文長度,實在容易被猜出來
      那如何超過明文長度咧...
      解法:不補空格,補0,在明文字串前方補足0,由於integer前面有0,也是當成0,所以沒差
      ex. $id = 50; $min_length = 4;
      $id = '0050'; // 補2個0,足4位
      在encryption_class.php裡
      function encrypt(){
          ...
          //$source = str_pad($source, $sourcelen);              //原作法
          $source = str_pad($source, $sourcelen, '0', STR_PAD_LEFT); //新的作法
          ...
      


References
Four ways to generate unique id by PHP
How to generate Unique Order Id (just to show touser) with actual Order Id?

星期四, 1月 19, 2012

該死的ie form

在html包form實在是在平常不過的事了
在firefox, chrome都跑的好好的
沒想到ie跑版,馬上開F12來看一下
天殺的那是在iframe裡... 要到該網頁又要帶參數....好想殺人
查了半天的css實是看不出原因

亂搬了一下form,居然有變化了
最後把margin設為0... 更.. 好了....
同事事後也說,他也遇過,說這form實在很奧妙....

忘了是ie什麼版本影響了... 總之先記下來
ie我恨你...

星期日, 1月 15, 2012

PHP5.3, CentOS,裝Oci8, pdo_oci8

沒連過oracle,一開始要用還真搞不太懂
載了2個檔案,共2G回來,還是不會用
最後看只需載個client的basic,供oci連線即可
看完網路一裝教學,還是裝不起來,在交叉比對下,終於成功了~~~

os: CentOS 6.4
php: 5.3
download Instant Client Downloads
自己的環境是linux 64bit, 所以載了 Instant Client for Linux x86-64
  1. Install oracle instant client
    • oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm
    • oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm
    • oracle-instantclient11.2-sdk-11.2.0.1.0-1.x86_64.zip
    # rpm -ivh oracle-instantclient11.2-basic-11.2.0.3.0-1.x86_64.rpm
    # rpm -ivh oracle-instantclient11.2-devel-11.2.0.3.0-1.x86_64.rpm
  2. 設定ORACLE_HOME
    設定ORACLE_HOME的提示真是讓我暈倒,說要指到lib
    設好了,但在install oci時,會掛,最後試出只要到"HOME"就好了
    看下面設定 vi /etc/profile
    export ORACLE_HOME=/usr/lib/oracle/11.2/client64
    export ORACLE_OWNER=oracle
    export ORACLE_SID=ora1
    export LD_LIBRARY_PATH=$ORACLE_HOME/lib
    export PATH=$ORACLE_HOME/bin:$PATH
    export TNS_ADMIN=$ORACLE_HOME/network/admin
    export NLS_LANG="AMERICAN_AMERICA.AL32UTF8"
    啟動環境變數
    source /etc/profile
  3. 解壓sdk並把裡面的sdk裡的資料複製到/usr/include
    # unzip oracle-instantclient11.2-sdk-11.2.0.1.0-1.x86_64.zip 
    # cp -fr instantclient_11_2/sdk/include/* /usr/include
  4. install oci
    • Installing OCI8 from PECL 
      • Use 'pecl install oci8' to install for PHP 8.
      • Use 'pecl install oci8-2.2.0' to install for PHP 7.
      • Use 'pecl install oci8-2.0.12' to install for PHP 5.2 - PHP 5.6.
      • Use 'pecl install oci8-1.4.10' to install for PHP 4.3.9 - PHP 5.1.

      p.s. 基本上裝最新版即可,它有向下相融
            就這麼簡單,過程會要求輸入ORACLE_HOME的位置,如果第3步有做的話,就按enter即可 如果找不到pecl,就先安裝pear

      yum install php-pear
      #如果找不到的話,就先增加repository
      rpm -Uvh http://repo.webtatic.com/yum/centos/5/latest.rpm
      yum --enablerepo=webtatic install php-pear

  5. 設定php.ini
    vi /etc/php.ini , add the line extension=oci8.so
    再重開apache即可
    # service httpd restart

    這時下php -m 就會看到oci8了~ 開心
  6. 測試
    <?php
    $option = array(
        'ip'            => '10.0.3.20',
        'port'          => '15210',
        'account'       => 'web',
        'password'      => 'FEF00CB',
        'service_name'  => 'WXS4'
    );
    
        $db = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST={$option['ip']})(PORT={$option['port']}))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME={$option['service_name']})))";
    
        if(function_exists('ocilogon')){
            $c1 = ocilogon($option['account'],$option['password'],$db) or die('OCI Connect error, wrong connection string');
            echo 'OCI Connect pass. yes!!!';
        }else{
            echo 'ocilogon not exists, installment is not correct';
        }
有看到某些文章指出要安裝pdo,自己裝了也一直失敗
後來發現php5.3已經有了,所以不用裝了

全手動安裝

在公司封閉的網路,只能手動安裝可以參考這篇 PHP 5.3 連線 Oracle 的客戶端及 PDO_OCI 模組安裝

issue
  • pdo_oci unsupported oracle version 
由於oracle instantclient可能出了新版,而pdo_oci未更新,可以直接改pdo_oci/config.m4 ,自己加上要的版本,search 一下unsupported version字眼,就可以找到,詳細可參考這篇 

p.s. 改完記得要先phpize --clean,不然configure的內容不會生效哦!!!

星期三, 1月 11, 2012

教授比較強!?

以前唸專科時,學校裡有教授頭術及碩士畢業的講師
曾經有個交大畢業的碩士講師跟我說過
有些學生比較看不起講師,覺得教授等級才夠看

專科時期,算是個人進入資訊領域的起萌期
老師個人當然還是有強弱,不過都覺得可學習的滿多的
也沒有感覺有沒有教授的頭銜有什麼差別

後來進了大學
老師都至少助理教授以上等級,且大多為40多歲以上
且教授等級的老師在業界或學術界都頗具名氣
聽課時,就真的覺得有差,除了講義上的東西,還可以講的更深入
一些理論的東西,也能講的比較活,感覺比較實用

有位教授說了句玩笑話:「教授就是專門把簡單的東西教的很難。」
原本只是會心一笑,後來才體會到,教授已經多年研究這領域,且每年都重複教這東西,已經成精了,而我們這些小毛頭,一時要聽懂,真的不是件容易的事。

所以...
碩士畢業的講師不敢說弱
只能說教授真的滿強的...

星期六, 1月 07, 2012

tmux改 screen 256 color

改了tmux的設定後,發現顏色沒有改
查了一下,知道可用tput color來看
只有8色,不支援256
可在config裡給screen-256color
set -g default-terminal "screen-256color"

不過開vim時,卻發生Terminal entry not found in terminfo 'screen-256color' not known
所以讀預色的ansi
搞的vim都沒顏色了,而且很多vim指令不能下

又看了一下要用
export TERM=screen-256color

不改還好,一改連tmux也進不去
出現 missing or unsuitable terminal: screen-256color

想改回去 已經不知原本的值了
幸好另一台server也有灌,看了原來本的設定是
TERM=screen
改回來就進tmux了

結論...
還是沒顏色... 有改回來就偷笑了
不過應該centos 沒有screen-256color這東西
想辦法搞定,應該就能work了

References

星期四, 1月 05, 2012

ci取db錯誤

codeigniget在db出錯時,會自行印出錯誤訊息,如果要關掉有兩種方法
  • config/database.php設定
    $db['default']['db_debug'] = TRUE;
  • 程式裡設定
    $this->db->db_debug = false;  
關掉錯誤訊息,那如何取得錯誤訊息咧
$this->db->_error_message(); 
因為不管關不關錯誤訊息try-catch都抓不到
所以如要判斷中斷程式得利用affected row
ci論談已經有人寫好function,可配合暫時關掉錯誤訊息,中斷和印出錯誤訊息
function insert_quiet($table = ‘’, $set = NULL)
  {
      $oldv =$this->db_debug;
      $this->db_debug = false;     
      $this->insert($table, $set);
      $e = $this->_error_message();
      $aff = $this->affected_rows();
      $this->db_debug = $oldv;
      if($aff < 1) {
        return($e);
      } else {
        return(true);
      }
  }
Reference