Thursday, November 5, 2015

Eclipse安装Maven

Maven是管理和下载jar包的工具。

如何安装:
Open Eclipse IDE
Click Help -> Install New Software...
Click Add button at top right corner
At pop up: fill up Name as "M2Eclipse" and Location as "http://download.eclipse.org/technology/m2e/releases"
Now click OK
After that installation would be started.

Go to Window --> Preferences
Observe, Maven is enlisted at left panel
Finally,

项目配置
Click on an existing project
Select Configure -> Convert to Maven Project

Monday, August 3, 2015

How to see websocket traffic in Chrome and Fiddler

Websocket是HTML5的一个重要功能,它让server和client端建立新的沟通channel, 让推送的功能更加快速。由于其省去每次发header这个步骤,测试表明websocket比Restful API要快三倍以上。不少网站已经开始使用websocket,比如six flags


这个网站可以测试websocket: https://www.websocket.org/echo.html

我们可以两个方法去看数据:
1. Google Chrome
Chrome在network tab可以看到这个websocket,frames可以看到data






2. Fiddler
在4.5版本中,可以加入额外的代码到custom js中:Rules > Customize Rules and add the following function inside your Handlers class,使得websocket数据显示在Log中:

static function OnWebSocketMessage(oMsg: WebSocketMessage) {
    // Log Message to the LOG tab
    FiddlerApplication.Log.LogString(oMsg.ToString());

    /*
    // Modify a message's content
    var sPayload = oMsg.PayloadAsString();
    if (sPayload.Contains("time")) {
        oMsg.SetPayload(sPayload + "... bazinga!");
    }
                          
    */
  }


Tuesday, July 21, 2015

Gmail API for C#

安装:
根据这个Quick start:https://developers.google.com/gmail/api/quickstart/dotnet



权限问题:
static string[] Scopes = { GmailService.Scope.GmailReadonly };

这句代码说明了权限只局限于Read email only,每次运行代码都会先检查权限文件C:\Users\KK\Documents\.credentials(自动生成,如果存在就会Cache)
如果要修改权限,比如改成
tatic string[] Scopes = { GmailService.Scope.GmailReadonly, GmailService.Scope.GmailModify, GmailService.Scope.GmailLabels};
运行代码前先要删除权限文件,因为默认下,它被cached了。





























Thursday, June 4, 2015

Partition in Win7



1. Shrink



2. Confirm shrink(use the default value)



3. New volumn




Thursday, May 28, 2015

Introduction to Xcode


How to add images in Xcode:
New Group images(in fact it shows as a folder)->drag the images to that group->select "copy to destination" in the pop-up window

How to add a new tab to tab bar controller:
drag a view controller to the stroyboard->right click the tab bar controller->(鼠标在黑龙江后面那个点会出现add)add new view controller and connect it to the new controller by dragging a line.


Create a plist:
http://nscookbook.com/2013/02/ios-programming-recipe-13-using-property-lists-plists/

Tuesday, May 19, 2015

Android加密算法: java变成jar然后到dll

Android用定制的BouncyCastle (轻量级加密算法)并且去除key长度限制

1. Java AES encrypt example:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class Encryptor {
    public static String encrypt(String key1, String key2, String value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(key2.getBytes("UTF-8"));

            SecretKeySpec skeySpec = new SecretKeySpec(key1.getBytes("UTF-8"),
                    "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(value.getBytes());
            System.out.println("encrypted string:"
                    + Base64.encodeBase64String(encrypted));
            return Base64.encodeBase64String(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static String decrypt(String key1, String key2, String encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(key2.getBytes("UTF-8"));

            SecretKeySpec skeySpec = new SecretKeySpec(key1.getBytes("UTF-8"),
                    "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] original = cipher.doFinal(Base64.decodeBase64(encrypted));

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {

        String key1 = "Bar12345Bar12345"; // 128 bit key
        String key2 = "ThisIsASecretKet";
        System.out.println(decrypt(key1, key2,
                encrypt(key1, key2, "Hello World")));
    }
}

2. JCE Unlimited Strength installation (java JCE download):
http://stackoverflow.com/questions/6363801/invalidkeyexception-illegal-key-size-java-code-throwing-exception-for-encryp
将local_policy.jar & US_export_policy.jar覆盖JRE security文件夹中的原始jar

3. How to export jar file in Eclipse (non-runnable jar):

if your code refers other libs, you need to copy the lib's source code in the src folder and compile together and can't use it as a jar reference.


4. convert jar to dll/exe for .Net by ikvm:

Ref:
http://stackoverflow.com/questions/15554296/simple-java-aes-encrypt-decrypt-example

Sunday, May 17, 2015

Design pattern 设计模式

Singleton pattern

Factory method/Abstract Factory pattern

Command pattern

Observer pattern

Provider design patter

Producer-consumer


singleton单例模式

顾名思义,就是一个class只能有一个instance。这是用得比较多的模式,场合主要是Util, database instance等。实现方法主要有两种:lazy initialization & eager initialization. 区别在于,eager总是产生一个新的instance.




public class SingletonDemo {
    private static SingletonDemo instance = null;
    private SingletonDemo() { }
 
    public static synchronized SingletonDemo getInstance() {
        if (instance == null) {
            instance = new SingletonDemo();
        }
 
        return instance;
    }
}


public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
 
    private Singleton() {}
 
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

Factory method pattern工厂方法/abstract factory pattern抽象工厂

wiki提供的例子,工厂方法,是对单一产品(button)的异化,而抽象工厂是进一步的工厂方法或者是多个产品组合(工厂级别)的异化。



//几个Button类 class Button{/* ...*/} class WinButton extends Button{/* ...*/} class MacButton extends Button{/* ...*/} //它们的工厂类 interface ButtonFactory{ abstract Button createButton(); } class WinButtonFactory implements ButtonFactory{ Button createButton(){ return new WinButton(); } } class MacButtonFactory implements ButtonFactory{ Button createButton(){ return new MacButton(); } }

class Button; // Abstract Class
 
class MacButton: public Button {};
 
class WinButton: public Button {};
 
class Border; // Abstract Class
 
class MacBorder: public Border {};
 
class WinBorder: public Border {};
对应的工厂是这样的
class AbstractFactory {
public:
    virtual Button* CreateButton() =0;
    virtual Border* CreateBorder() =0;
};
 
class MacFactory: public AbstractFactory {
public:
    MacButton* CreateButton() { return new MacButton; }
    MacBorder* CreateBorder() { return new MacBorder; }
};
 
class WinFactory: public AbstractFactory {
public:
    WinButton* CreateButton() { return new WinButton; }
    WinBorder* CreateBorder() { return new WinBorder; }
};

Provider design pattern提供程序模式

提供程序模式是一个简单的模式,主要是为了减少代码复用而提高代码重用率而设计的模式,只在.Net框架中提供。ProviderBase是.Net提供的基础类. 它其实是继承的一种变体,从xml中读取各种继承的类的名字,从而一起调用一个基类方法实现不同类的同一行为。
下面是一个例子,用于得到不同酒店的价格。

public abstract class HotelProviderBase : ProviderBase
{
       int RunId;
       void setProxy(String proxy){}
       public abstract void UpdateHotels(JobRequest request, int runId);
}

public sealed class ExampleHotelProvider : HotelProviderBase
{
       private void UpdateHotel(JobRequest request){}    
}


public abstract class HotelProviderManager
{
         private static void LoadProviders()
        {
                //load class from hotel.xml
                 _providers = new HotelProviderCollection();
                 ProvidersHelper.InstantiateProviders(section.Providers, _providers, typeof(HotelProviderBase));
        }
}


public sealed class HotelManager 
{
        public void onRun()
       {
                  foreach (HotelProviderBase provider in HotelProviderManager.Providers)
                  {
                            if (provider.Enabled)
                            {
                                provider.UpdateHotels(request, (int)Log.RunId);
                            }
                   }
          }
}

hotel.xml
<add name="ExampleHotelProvider"
         type="ExampleHotelProvider"
         siteId="4"
         siteName="http://www.example.com"
         tableName="HotelRates_Example_Hotels">

http://www.cnblogs.com/webabcd/archive/2007/01/22/626479.html

命令模式Command pattern

由wiki里面的定义,命令模式是把action封装起来,方便重复使用。

下面演示一个测试android app基于UiAutomator的程序
1. EventInput: 首先定义event/command的输入参数
2. Events: 一系列的actions
3. Operator: 对应不同的input,invoke相应的action
4. Main class: 列出所有input, 然后operator开始做事

public abstract class EventInput {
public EventInput followingInput;
}

import java.util.ArrayList;
public class ClickEventInput extends EventInput{

protected String target;

//for GetListValues
public ClickEventInput(){}
public ClickEventInput(EventInput followingInput)
{
this.followingInput = followingInput;
}

public ClickEventInput(String target)
{
this(target,null);
}

public ClickEventInput(String target, EventInput followingInput)
{
this.target = target;
this.followingInput = followingInput;
}

}

public class Events {
       protected static Operator op;

protected Events(Operator op)
{
this.op = op;
}

public void Click(UiDevice device, String buttonName, EventInput followingInput) throws UiObjectNotFoundException
{
try
{
 if(new UiObject(new UiSelector().text(buttonName)).exists())
new UiObject(new UiSelector().text(buttonName)).clickAndWaitForNewWindow();

}
    catch(Exception e)
    {
    Util.Log(3, "Can't press button", buttonName+","+e.toString());
    return;
    }

if(followingInput!=null)
  op.InvokeAction(followingInput);
}
}


如果有其他行为,写custom类覆盖
public class CarEvents extends Events{

public CarEvents(Operator op) {
super(op);
}

public void Click(UiDevice device, String buttonName, EventInput followingInput) throws UiObjectNotFoundException
       {
        }
}


public class Operator{

UiDevice device;
EventInput input;

        public void InvokeAction(EventInput input)
{
Class cls = null;
Object value = false;

            Class[] constructorArg = new Class[1];
            constructorArg[0] = Operator.class;
            Object obj = cls.getDeclaredConstructor(constructorArg).newInstance(this);

            if(input instanceof ClickEventInput)
            {
            Method method = null;
                Class[] cArg = new Class[3];
                cArg[0] = UiDevice.class;
                cArg[1] = String.class;
                cArg[2] = EventInput.class;
                
                ClickEventInput cInput = (ClickEventInput)input;
                method = cls.getMethod("Click",cArg);
                method.invoke(obj,device,cInput.target, input.followingInput);
            }

}
}

public class NewCar extends UiAutomatorTestCase {   

public void testDemo() throws UiObjectNotFoundException {   

             EventInput input = new ClickEventInput("MAKE & MODEL",,new SleepEventInput(3));
             Operator op = new Operator(getUiDevice(), input,"Car", CarEvents.class);
             op.Start();
        }
}
        

Saturday, March 21, 2015

Postgres SQL


btim, length: (remove those records with invalid chars only like **()*%0_  )
select * from stocks
where length(btrim(description,' <>=*@_''-?%&()/":`.0'))>0
limit 10000

upper: (case sensitive)
select upper('aa')

replace:
replace('gary sham'.'sham','cen')

concatenate:
string||string

regex:
http://www.postgresql.org/docs/8.3/static/functions-matching.html

--remove price, g means replace all, no g means replace once
update aaa
set des = regexp_replace(des,E'\\$\s*[0-9,\\.]*','------------','g');

--get 1st blocks specified by regex
(regexp_matches(des,E'\\w+.*\\w+'))[1]

--get 5th separate blocks splitted by10+ dashes, regex for splitter
(regexp_split_to_array(des,E'\\-{10,}'))[5]

reverse:
https://wiki.postgresql.org/wiki/Reverse_string(supports only above 8.3)

data type:
http://www.postgresql.org/docs/9.3/static/datatype.html

string:
http://www.postgresql.org/docs/9.1/static/functions-string.html

operator:
http://www.postgresql.org/docs/6.3/static/c09.htm

vacuum space:
Vacuum city_table

Function:
call:
select run_proc()

define:
CREATE OR REPLACE FUNCTION run_proc() RETURNS void AS $func$
DECLARE
    func_body text;
BEGIN
    func_body := '
update descr d
set formatted_city=city
from loc c
where c.state=d.state' ;

    EXECUTE func_body;
END;
$func$ LANGUAGE plpgsql;

Function example:
--drop FUNCTION singular2plural(input text)
create FUNCTION singular2plural(input text) RETURNS text
LANGUAGE plpgsql IMMUTABLE STRICT AS $$
DECLARE
    result text = '';
    root text;
    suffix text = '';
    pluralres text = '';
    VOWELS text = 'aeiou';
BEGIN
  IF btrim(length(btrim(input)))=0 then
     return input;
  END IF;
  IF length(regexp_replace(btrim(input), E'(\\w+\\s*)*','','g'))>0 then
RAISE EXCEPTION 'singular2plural contains invalid character';
  END IF;

  SELECT  plural INTO pluralres
        FROM    aa_aberrant_plural_map
        WHERE   singular = $1;

  if pluralres<>'' then
      return pluralres;
  end if;
  root = input;
  if substring(input,length(input)) = 'y' AND strpos(VOWELS,substring(input,length(input)-1,1))=0 then
       root = substring(input,1,length(input)-1);
       suffix = 'ies';
  elsif substring(input,length(input)) = 's' then
 if strpos(VOWELS,substring(input,length(input)-2,1))>0 then
   if substring(input,length(input)-3)='ius' then
root = substring(input,1,length(input)-2);
suffix = 'i';
            else
                root = substring(input,1,length(input)-1);
                suffix = 'ses';
            end if;
          else
   suffix = 'es';
 end if;
  elsif substring(input,length(input)-1)='ch' or substring(input,length(input)-1)='sh' then
        suffix = 'es';
  else  suffix = 's';
  end if;
  result = root||suffix;
  RETURN result;
END$$;

Function example:
drop FUNCTION if exists aa_sp_cat();
CREATE FUNCTION aa_sp_cat() RETURNS void AS $$
   update q set city='New York' from cities c where cityid=5;
$$ LANGUAGE SQL;

Table options:
Create table products

    productid integer,
    desc varying_character
) with (Appendonly=true, compresslevel=5, orientation=column)
Distributed by (productid);

appendonly=can only insert records, no delete/update
orientation=separate table by columns
partition=separate table into bulks of rows
Distributed=physical storage key

Impot data from file using psql:
create table city_table
(
   city character varying(100)
   ,stateabbr character varying(10)
)

1. Start  psql with the following command: psql.exe -h 10.10.10.10 -d databasename
2. CTP_4M->  \copy  public.city_table from C:\city.csv with csv header quote as '"'

in city.csv, column names: city, stateabbr

Thursday, March 5, 2015

HTTP POST简介

在研究postmates的API时候https://postmates.com/developer/docs要知道怎么用POST来得到数据

基本URL为https://api.postmates.com/v1/customers/:customer_id/delivery_quotes
API key和customer id从这里可以得到https://postmates.com/developer/testing
所以URL为https://api.postmates.com/v1/customers/cus_KEX15lMKh_770k/delivery_quotes

postmates提到
"Authentication is specified with HTTP Basic Authentication
POST data should be encoded as standard application/x-www-form-urlencoded

The Postmates API requires authentication by HTTP Basic Auth headers. Your API key should be included as the username. The password should be left empty."

Authorization(request header):
Basic access authentication(http://en.wikipedia.org/wiki/Basic_access_authentication)提到client side要a string "username:password"且用Base64加密后在前加上Basic+空格
d067ca26-7eb8-4dab-bebf-30ba3601e0f2:结果是
Authorization: Basic ZDA2N2NhMjYtN2ViOC00ZGFiLWJlYmYtMzBiYTM2MDFlMGYyOg==

Post data:
由上述理论提到post data要用form-urlencoded形式
在request header中加入
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
这个content type也决定了request body用http get的parameter形式name1=value1&name2=value2而不是json形式







request body:
pickup_address=165 Broadway, New York, NY&dropoff_address=2 gold st, New York, NY

在fiddler显示最后的结果为
















返回结果:



Thursday, February 5, 2015

用Fiddler捕捉phone的traffic

具体细节参看官网:http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/ConfigureForiOS
1. phone & 电脑连接同一个wifi
2. 获取电脑的IP地址, 并且输入到phone的wifi设置中,port 8888是fiddler默认的。

























3. 在Fiddler中设置options->connections->Allow remote computers to connect以及安装Certificate Maker plugin。
4. 在Fiddler中设置options->HTTPS->Actions->Trust root certificate
5. iphone6以上还需要信任证书Settings -> General -> About -> Certificate Trust Settings。登录手机 浏览器,输入地址192.168.1.3:8888。如果看见Fiddler Echo Service说明成功。

6. 可选项:fiddler中设置或者HTTPS
此时我们可以见到fiddler开始捕捉手机上的traffic,当然电脑上的traffic也会捕捉,process可以区分出他们,chrome是来自电脑,空白的是来自phone















7. 如上图所示,有的traffic会显示tunnel to,表示这些request用了SSL,我们在手机安装一些证书来骗过这些网站从而获得细节
电脑中fiddler的网址是http://localhost:8888/     证书也位于这里
在手机我们输入电脑的IP,port是8888,就可以访问该网址,如上述例子,我们在手机浏览器输入http://192.168.1.3:8888/  我们见到一个hyperlink: you can download the Fiddler certificate
安装了之后,就可以看到这些traffic了,不过不是所有SSL都可以骗,比如twitter就不可以了。
要删除fiddler cert可以settting->general->profile(iphone)

重新安装Fiddler的话都要重新再手机上安装此证书,在iphone中,证书通过以上方法可能打开不了,可以在fiddler把证书下载下来Options->HTTPS->Actions->Export root cert to desktop然后通过邮件发到手机即可打开。

























Android的配置:
http://docs.telerik.com/fiddler/Configure-Fiddler/Tasks/ConfigureForAndroid

另一个Post

Monday, February 2, 2015

Selenium in C# - Browser Automation

OpenQA.Selenium:
Start: http://docs.seleniumhq.org/docs/03_webdriver.jsp
SetPreference: http://seleniumeasy.com/selenium-tutorials/firefox-profile-preferences-using-selenium-webdriver

FindElement(By): http://selenium.googlecode.com/git/docs/api/java/org/openqa/selenium/By.html?_sm_au_=iVVsMF35HZfF7QWj

FirefoxProfile profile = new FirefoxProfile();
profile.SetPreference("network.proxy.http", "1234");
FirefoxDriver browser = new FirefoxDriver(profile);
browser.PageSource.Contains("abcd");
IWebElement total = browser.FindElement(By.ClassName("ddd"));//css class
String totalStr = total.Text;

ReadOnlyCollection<IWebElement> children = total.FindElements(By.ClassName("eee")).FindElement(By.ClassName("fff"));
foreach (IWebElement product in children){}
String innerHtml = total.GetAttribute("innerHTML");
total.Click();

//selelium's approach: scroll an element into view
browser.ExecuteJavaScript("arguments[0].scrollIntoView(true);", total);

xpath
("//div[@class='abc']")[1]
("//div[contains(@class, 'abc']")//h4[contains(text(), 'bb')]


KB: C#

AppSettingsReader:
Read app.config file

XmlDocument & XmlNode (Read XML file):
XmlDocument configDoc = new XmlDocument();
configDoc.Load(fileName);
XmlNode oneNode = configDoc.SelectSingleNode("//config/");
String abc = botNode.Attributes["proxy"];

Attribute & CustomAttributeData:
FieldInfo[] fs = obj.GetType().GetFields();
foreach (FieldInfo f in fs)
{
IList<CustomAttributeData> attributes = CustomAttributeData.GetCustomAttributes(f);
        foreach (CustomAttributeData attribute in attributes)
        {
             //check if the field was marked as [ConfigValue]
             if (attribute.Constructor.DeclaringType.Equals(typeof(ConfigValue)))
    {}
}
}



    [AttributeUsage(AttributeTargets.Field)]
    public class ConfigValue : Attribute
    {
        private String prameName;
        public ConfigValue(String name)
        {
            prameName = name;
        }

    }

    [AttributeUsage(AttributeTargets.Field)]
    public class RegexFile : Attribute
    {
        private String fileName;
        public RegexFile(String name)
        {
            fileName = name;
        }
    }


Use:
        [ConfigValue]
        String proxy;

        [RegexFile("rabc.regex")]
        private Regex rabc;

Friday, January 16, 2015

KB: VB

VBScript:
aa.bat:
rem wscript abc.vbs male
cscript abc.vbs male

abc.vbs:
set wnet =CreateObject("WScript.Network")
uname=wnet.UserName
uage = InputBox("Please enter your age")
gender = WScript.Arguments(0)
MsgBox "Your user name is " & uname & "," & uage & "," & gender

Friday, January 2, 2015

Publish your Android app


1. Generate key
     http://www.apkbus.com/android-44559-1-1.html





















2. Go to Google Play Developer page to publish the app (registration fee $25 for lifetime)

Ref:
http://developer.android.com/distribute/index.html
http://mobile.51cto.com/android-228966_all.htm