2011年5月17日 星期二

學而不用則荒廢、不學東西則懶散

20110509-sunny


趁著天氣好時,拍一張,有時並不是天天都有好風景,但換個角度仍是又一村啊。


子曰:「學而不思則罔,思而不學則殆。」身在一處專碰新技術的單位,這半年開始會有這樣的念頭。天天有機會接觸新的東西,但總是沒那個展現環境,派不上用場,時常觀察新趨勢,左看看右看看,手上的成品卻不曾一點茁壯。之前也寫過一篇心得:戒了 iPhone、iPod touch 和 iPad 產品,深深覺得真正有價值的不是多酷炫的 UI 、高效率的程式,而是使用者當下情愫下,生產出來的內容。然而,就該因為這些停步嗎?我想這又有點本末倒置了,這之中必須尋求一個平衡點。


趁著今天的萬安演習,跟隔壁 team 的同事閒聊幾句,我問他是否念博班,他跟我說他喜歡寫 code 所以很明確現在不想追求學問。幾天前跟幾位大學同學閒聊,發現不少人擁有高薪生活,但工作內並非寫程式。


打算少用 Social Network Service 好了,最近覺得 Social Network 只是另類的孤獨方式,看起來好像很快樂,實際上卻甚麼也沒留下。專心一下,產生一些足跡吧!


2011年5月16日 星期一

[PHP] 使用 cURL POST 上傳檔案

好久沒寫 PHP 了,連自己工作的機器上都忘了安裝 orz 這半年一直都在寫 python 啊,這次使用 PHP 來模擬短時間的大量連線。


在 Ubuntu 的安裝:


$ sudo apt-get install php5-cli php5-curl


之前只有透過 curl 使用 POST 送出 text 類的資料,這次想要模擬檔案上傳,一開始使用:


$POST_DATA = array( 'my_file' => file_get_contents( '/path/my_file' ) );


但還是送不出去,最後才發現要用:


$POST_DATA = array( 'my_file' => '@/path/my_file' );


大概是這樣才會被轉換使用 multipart/form-data 的方式,完整範例:


<?php

        $url = 'http://host/upload';

        $ch = curl_init();
        curl_setopt( $ch, CURLOPT_URL, $url );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
        curl_setopt( $ch, CURLOPT_POST, true );
        curl_setopt( $ch, CURLOPT_POSTFIELDS, 
array(
               //'my_file' => file_get_contents( '/path/my_file_data' ) 
               'my_file' => '@/path/my_file_data' 
)
);  
        echo curl_exec( $ch );
        curl_close( $ch );
?>


2011年5月15日 星期日

[C] C 語言,使用 Perl Compatible Regular Expressions (PCRE)

幾年前也寫過一篇:[C] C 語言,使用 Regular Expressions,那時是使用 Regex library 也曾說過要用看看 PCRE 啦,結果日子久了就都忘光光,倒是前陣子在 visual studio 編譯 c++ project 時,發現怎都忘光光 Orz 所以來寫一篇筆記吧。


至於 PCRE 的好處嘛,如果常開發 PHP 並使用 preg_match 或 preg_match_all 等相關函式庫的話,那使用的語法一致的啦。


簡單的 main.c 範例:


#include <pcre.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main( int argc, char ** argv)
{
        pcre *re;
        const char *error;
        int erroffset;
        int ovector[30];
        int options = 0;

        if( argc < 3 )
        {
                printf("Usage> %s \"PCRE_PATTERN\" \"TEST_DATA\"\n", argv[0]);
                return 0;
        }
        if( ( re = pcre_compile( argv[1], options, &error, &erroffset, NULL) ) == NULL )
        {
                fprintf(stderr, "PCRE compilation failed at offset %d: %s\n", erroffset, error);
                exit(1);
        }
        if( pcre_exec(re, NULL, argv[2], strlen(argv[2]), 0, 0, ovector, 30) >= 0 )
                printf("Match\n");
        else   
                printf("Not Found\n");
        return 0;
}


在 FreeBSD 編譯:


如果系統已經安裝過 pcre 相關 lib 的話,僅需編譯程式時,指定函式庫相關資訊即可


> gcc -I/usr/local/include -L/usr/local/lib -lpcre main.c


如果沒有安裝過,那只好去 PCRE - Perl Compatible Regular Expressions 官方網站下載原始碼來編譯一下。


> cd pcre_test
pcre_test> wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.12.tar.gz
pcre_test> tar -xvf pcre-8.12.tar.gz && cd pcre-8.12
pcre_test/pcre-8.12> cd pcre-8.12
pcre_test/pcre-8.12> ./configure && make && cd ..
pcre_test> ls
main.c          pcre-8.12/        pcre-8.12.tar.gz


pcre_test> gcc -DHAVE_CONFIG_H -DPCRE_STATIC -Ipcre-8.12 pcre-8.12/pcre_chartables.c pcre-8.12/pcre_compile.c pcre-8.12/pcre_config.c pcre-8.12/pcre_dfa_exec.c pcre-8.12/pcre_exec.c pcre-8.12/pcre_fullinfo.c pcre-8.12/pcre_get.c pcre-8.12/pcre_globals.c pcre-8.12/pcre_info.c pcre-8.12/pcre_maketables.c pcre-8.12/pcre_newline.c pcre-8.12/pcre_ord2utf8.c pcre-8.12/pcre_refcount.c pcre-8.12/pcre_study.c pcre-8.12/pcre_tables.c pcre-8.12/pcre_try_flipped.c pcre-8.12/pcre_ucd.c pcre-8.12/pcre_valid_utf8.c pcre-8.12/pcre_xclass.c pcre-8.12/pcre_version.c pcre-8.12/pcreposix.c main.c



pcre_test> gcc -Ipcre-8.12 main.c pcre-8.12/.libs/libpcre.a


pcre_test> ls
a.out*            main.c          pcre-8.12/        pcre-8.12.tar.gz


測試:


pcre_test> ./a.out 
Usage> ./a.out "PCRE_PATTERN" "TEST_DATA"
pcre_test> ./a.out "<a></a>" "<a>test</a>"
Not Found
pcre_test> ./a.out "<a>(.*?)</a>" "<a></a>"
Match


在 VC++ 編譯:


PCRE 內附 cmake 編譯方式,正統的方式應該是透過 cmake 編譯出 lib 來使用,在這邊就手動調調,直接用 src 把玩一下。


建立 2 個 projects,其中一個是 libpcre 另一個則是 main,前者是 PCRE 的相關資料,後者是上述的 main.c 例子。對 libpcre 來說,先把壓縮檔內 config.h.generic、pcre.h.generic 和 pcre_chartables.c.dist,分別複製成一份 config.h、pcre.h 和 pcre_chartables.c。


source, header


接著設定兩個 projects 的 properties 等,對 libpcre 和 main 兩者來說:


[C/C++] -> [General] -> [Additional Include Directories] 加入 pcre-8.12 的目錄位置


[C/C++] -> [Code Generation] -> [Runtime Library] 設定為 Multi-threaded (/MT) ,理由是我要用 static 的,並且不想使用 DLL ,這樣才比較 portable 。


multi-threaded


對 libpcre 個別設定:


[General] -> [Configuration Type] 設定為 Static library (.lib)


[C/C++] -> [Preprocessor] -> [Preprocessor Definitions] 加 HAVE_CONFIG_H;PCRE_STATIC; 


對 main 個別設定:


[Common Properties] -> [Framework and References] -> [Add New Reference],請加入 libpcre


[C/C++] -> [Preprocessor] -> [Preprocessor Definitions] 加 PCRE_STATIC; 即可


[Project Dependencies],對 main Projects 請勾選 libpcre ,這樣編譯過程會先編 libpcre


dependencise


如此一來就能夠 build 出來啦


其他筆記:


如果編譯過程中會有 error LNK2001: unresolved external symbol __pcre_default_tables 的話,那應該是 libpcre 編譯過程中少了 pcre_chartables.c 檔案,可以從 pcre_chartables.c.dist 複製出來;若是 error LNK2019: unresolved external symbol __imp__pcre_exec referenced in function _main 這類的,那應該是 main project 之 preprocessor definitions 忘了加 PCRE_STATIC  或是 Framework and References 要加一下 libpcre 囉


2011年5月11日 星期三

專利啊

有幸參與公司專利的提案,透過長輩的指導,讓我對專利有初步的了解。青蛙希望可以分享一下下,在此就稍微筆記一下心得,細節還需多多參與專利課程才能補齊。


由於我並沒有參與專利課程,所以對於專利的觀念應該很不完整,僅供參考。



  1. 專利最初的目的是用來保護自己的發明

  2. 專利可以分成發明、再發明和新樣式,三種型態

  3. 提出的專利,必須不能被其他專利、論文所揭露過的概念(須調查各國專利或請事務所專利工程師協助)

  4. 假設 A 專利的元素是 a, b, c 三種元素,而 B 專利是 a, b, d 元素,那 B 專利還是可以申請;假設 C 專利是用 a, b, c, e 的話,還是可以申請,但行使時,必須有 A 的專利授權 

  5. 申請專利不難,僅需把專利範圍寫好不要踏到別人的專利,最大的負擔是申請過程和費用

  6. 申請專利和維護是需要費用的,在公司發專利就是公司出錢,因此也會有嚴格的審核過程,例如考慮專利的價值,而發明人與公司存在一種利益比例

  7. 專利範圍越大對公司越有價值,代表別人容易踏到你的專利,但已有跳脫(1)的本意,因為一些發明通常是從小地方萌芽,例如最初研發是要給小孩的踏步車,成果卻想把範圍寫到機車、汽車甚至飛機也被包含等

  8. 演算法類的專利比較好申請,但抓不到(無價值?又把方法告訴別人);偏 UI、系統類的專利比較好抓,但不太好申請(審核時容易被模糊焦點,或是說 ooo 也有類似的功能)

  9. 專利是有國家限定的,例如在美國申請專利通過,該專利就僅限於美國。所以才有 A 公司拿著美國專利告 H 公司,想要限制 H 公司不能在美國販賣商品

  10. 專利是可以被推翻的。除此之外,假設在同一個專利在美國、台灣都有,但美國專利被推翻時,將導致敵手拿著美國專利無效的結果,要求台灣專利也無效

  11. 專利的發明人千萬不要給別人掛名,因為推翻專利最簡單的方式就是找其中之一的發明人詢問,若對方答不出來容易被判斷成無效專利

  12. 專利是法律文件,重邏輯性,因此不好閱讀或撰寫


申請專利前,還是多想想 (1) 吧!不然蔓延下去就快跟嘴砲沒兩樣。開發系統時,若牽扯到授權販賣給廠商時,容易被詢問是否有專利,這是廠商用來保護自己的。如果不想申請專利保護自己,又不想被別人專利,那就可以發 paper 揭露想法,或是一些公開處加以發布想法。除此之外,別人說有專利,那還得看看專利是否有效,通過的專利是一回事,無效的專利又是另一回事。


最後,專利看多時,會發現一些很基本的概念竟然都被申請專利了,不就代表別人可以拿著專利告你嗎?只是提告時會需要證據,大概是蒐證的難易問題。其次,專利感覺還是有錢人在玩的遊戲 XD 因為申請要錢,維護也要錢啊,會覺得:


專利是拿來保護發明人;專利是有錢人才玩得起的;這樣是否代表專利是用來保護有錢人繼續有錢呢?


2011年5月6日 星期五

[Android] Android Market and AOSP @ Nexus One、Android 2.3.3

android_market01 android_market02


之前嘗試編譯 AOSP 後,發現編譯後裡頭很乾淨,連 Android Market 都沒有,頓時不知道該怎樣安裝軟體,變成安裝軟體必須找到 apk 檔案,並且使用 adb install *.apk 或 adb push *.apk /system/app 的方式安裝,十分不方便,我有嘗試從 Apps - Android Market 網頁安裝,但都沒反應?!所以就著手研究在 AOSP 上安裝 Android Market 的嘗試,倒是看了不少文章都說 AOSP 預設是不會包含任何 Google app 的,可能是 License 問題或是 Google 並沒有 Open source 的關係,總之找到的解法要嘛就是去跟 Google 要(?),不然就是安裝網路上可以找到的 android market.apk 檔案,只是 android market 使用上會需要綁帳號的,對於別人做的東西還是要三分保留啊,以免帳密被第三方取得!總之,我就東看看西摸摸,搞懂了一些東西,決定從原先 Android 2.3.3 中取得相關 Android market 程式,拼拼湊湊弄出功能囉。


首先,從 Nexus One with Android 2.3.3 裡,在 /system/app 裡撈出 Android Market app,但找了很久都沒看到!最後才知道,這個 Android market app 是叫作 Vending.apk 啦,但是擺進 AOSP 裡後,卻看不到 Android Market 耶?找了一些文章,才知道 Nexus One 裡的 Google app 都有兩種東西: apk 跟 odex 檔案,兩者要搭配在一起才能使用,但我把兩者透過 adb push 到 AOSP 裡也依舊看不到,所以就改從事反組譯類的工作 XD 


把玩"魔術師" -- 認識、把玩 APK 檔 這篇文章中,得知 odex 是最佳化後的產物並且搭配 apk 使用的,如果要整合成使用單一 apk 檔,就必須整 odex 資訊整合回 apk 啦。多虧這篇文章,我又認識 dsixda Android Kitchen。簡單來說,這是一個製作客製化 ROM 的整合工具,包括建立 ROM 啊、重新 sign apk 等,我只需要的是將 odex 整進 apk 檔案,這些東西是分類在 decode 部分。


參考 Android Kitchen 之 decode 後,得知負責 decode 的也有 open source:smali - An assembler/disassembler for Android's dex format,而取得 smali.jar baksmali.jar 後,就能工作啦!


總結流程:



  1. 從 Nexus One with Android 2.3.3 官方環境中,取得 Android Market 及其相關函式庫(主要是 Vending 跟 GoogleServicesFramework)


    • $ adb pull /system/app /tmp

    • $ adb pull /system/framework /tmp

      • 這不見得需要,因為我後來在 decode 的過程中並沒使用 XD





  2. 使用 smali 將 odex 整進 apk 中

    • 將 Vending.odex 併入 Vending.apk

    • 將 GoogleServicesFramework.odex 併入 GoogleServicesFramework.apk

    • 連續動作,假設 Vending 跟 GoogleServiceFramework 都擺在 app 中:

      • $ ls
        app  baksmali-1.2.6.jar  framework  smali-1.2.6.jar

        $ ls app
        GoogleServicesFramework.apk  GoogleServicesFramework.odex  Vending.apk  Vending.odex

        $ java -Xmx512m -jar baksmali-1.2.6.jar -d framework/ -x app/Vending.odex
        $ java -Xmx512m -jar smali-1.2.6.jar -o classes.dex out           
        $ zip -r -q app/Vending.apk classes.dex
        $ rm -rf out/ classes.dex

        $ java -Xmx512m -jar baksmali-1.2.6.jar -d framework/ -x app/GoogleServicesFramework.odex
        $ java -Xmx512m -jar smali-1.2.6.jar -o classes.dex out
        $ zip -r -q app/GoogleServicesFramework.apk classes.dex
        $ rm -rf out classes.dex






  3. 將整合好的 Android Market 及相關函式庫擺進 AOSP 裡

    • 使用 adb install

      • $ adb install Vending.apk 
        1172 KB/s (1091549 bytes in 0.909s)
                pkg: /data/local/tmp/Vending.apk
        Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]

      • 算是預期中的結果 XD 解法應該是重新 sign apk

        • $ java -jar signapk_files/signapk.jar signapk_files/testkey.x509.pem signapk_files/testkey.pk8 GoogleServicesFramework.apk GoogleServicesFramework-signed.apk
          $ java -jar signapk_files/signapk.jar signapk_files/testkey.x509.pem signapk_files/testkey.pk8 Vending.apk Vending-signed.apk
          $ adb install GoogleServicesFramework-signed.apk
          1196 KB/s (1123115 bytes in 0.917s)
          pkg: /data/local/tmp/GoogleServicesFramework-signed.apk
          Success
          $ adb insatll Vending-signed.apk
          1221 KB/s (1089904 bytes in 0.871s)
          pkg: /data/local/tmp/Vending-signed.apk
          Success

        • 但開始使用時,卻發現無法登入 Google,猜想應該是重新 sign apk 的影響,所以就改用 adb push 啦





    • 使用 adb push

      • $ adb root
        restarting adbd as root
        $ adb remount
        remount succeeded
        $ adb push Vending.apk /system/app
        1150 KB/s (1091549 bytes in 0.926s)
        $ adb push GoogleServicesFramework.apk /system/app






收工!接著就可以從 AOSP 啟用 Android Market 囉!一開始執行會看到一個 alert 錯誤視窗,但流程接著是選擇網路、指定 Google Account 後,重新啟動 market 後是正常了,嘗試安裝一下 Angry Birds,跑起來沒啥問題,應該是搞定啦。


android_market03 android_market04 android_market05 android_market_2.13


目前的 Android Market 是 2.13 版,網路上倒可以找到 2.2.11 版的,但我沒啥需求,先用這就好 :D 這篇主要是學到整合 odex 跟 apk 的方式囉,接下來就可以專心改改 AOSP 啦!