2011年12月10日星期六

一直以来,我都以为UTF-16和UCS-2是一样的 囧。

UCS-2: 固定双字节表示一个字符,只能表示 UCS 的子集 BMP。
       (UCS-2 扩充后成为 UTF-16,这里我们依然将 UCS-2 指代扩充前的编码方式)
UCS-4: 固定四字节表示一个字符,能表示整个 UCS。
UTF-16: 双字节或者四字节表示一个字符,能表示整个 UCS。
        UCS-2 跟 UTF-16 在 BMP 范围兼容。 UCS-2 是废弃的。
UTF-8: 一种编码方式,一到四个字节(*)表示一个字符,能表示整个 UCS。
UTF-32: 同 UCS-4。

*现在的 Unicode 标准只有 21 位 0 ~ 0x10FFFF

2011年12月9日星期五

使用javamail生成带附件的html邮件

一般来说,带附件并且有图片的html的mime邮件形如以下的格式:

 multipart/mixed
    multipart/related
        multipart/alternative


JavaMail的FAQ没有详细解释如何发送这种多重嵌套multipart的mime邮件。关键是设置content-type为"message/rfc822",见下面示例代码的黑体部分。

public void createMail() {
 ......
 //这里只示例生成Multipart的代码,其他代码请参考JavaMail的相关文档
 Multipart mmp = null;
 mmp = getHtmlPart(plaintext, html);
 mmp = getRelatedPart(mmp, image);
 mmp = getMixedPart(mmp, attachment);
 ......
}

private Multipart getHtmlPart(String plaintext, String html) throws MessagingException {
 MimeMultipart mmp_alt = new MimeMultipart("alternative");
 MimeBodyPart mbp_text = new MimeBodyPart();
 mbp_text.setContent(plaintext, "text/plain;charset=UTF-8");
 mmp_alt.addBodyPart(mbp_text);
 MimeBodyPart mbp_html = new MimeBodyPart();
 mbp_html.setContent(html, "text/html;charset=UTF-8");
 mmp_alt.addBodyPart(mbp_html);

 return mmp_alt;

}

private Multipart getRelatedPart(Multipart aPart, String imagesPath) throws MessagingException, UnsupportedEncodingException {
 MimeMultipart mmp = new MimeMultipart("related");

 MimeBodyPart mbp = new MimeBodyPart();
 mbp.setContent(aPart, "message/rfc822");
 mmp.addBodyPart(mbp);

 String[] imageFiles = imagesPath.split(",");
 if (imageFiles.length != 0) {
  for (String file : imageFiles) {
   MimeBodyPart mbp_file = new MimeBodyPart();
   FileDataSource fds = new FileDataSource(file);
    mbp_file.setDataHandler(new DataHandler(fds));
   mbp_file.setFileName(MimeUtility.encodeText(fds.getName(), "gbk", "B"));
   File f = new File(file);
   mbp_file.setContentID("<" + f.getName() + ">");
   mmp.addBodyPart(mbp_file);
  }
 }
 return mmp;
}

private Multipart getMixedPart(Multipart aPart, String attachPath) throws MessagingException, IOException {
 MimeMultipart mmp = new MimeMultipart("mixed");

 MimeBodyPart mbp = new MimeBodyPart();
 mbp.setContent(aPart, "message/rfc822");
 mmp.addBodyPart(mbp);

 String[] files = attachPath.split(",");
 if (files.length != 0) {
  for (String file : files) {
   MimeBodyPart mbp_file = new MimeBodyPart();
   mbp_file.attachFile(file);
   mbp_file.setHeader("Content-Transfer-Encoding", "base64");
   mmp.addBodyPart(mbp_file);
  }
 }

 return mmp;
}

salt解释

以前翻阅文档是总会遇上salt这个词,但一直没有理解,今天看到这篇文章,才明白是怎么回事。
salt是一串随机(但是对每个用户是固定的,比如用户名、用户id等)的字符串,附加到密码上生成心得字符串,再用这个字符串生成md5,保存到数据库中。
使用salt和单纯的密码md5比较,有2个好处:
1. 增加破解的难度。数据库在被hack的情况下,如果不知道salt的生成规律,是无法简单地通过字典来暴力破解。
2. 增加破解的时间。即使知道salt生成规律,通过字典暴力破解也只能每次破解一个用户的密码,因为每个用户的salt是不一样的,最终生成的md5也不相同。
而如果只简单保存密码的md5,那么不同用户密码相同的时候,可以通过一次sql查询就破解。

顺便吐槽下,salt其实并不难理解,但是在看定义和用途的解释却让人很难理解。说的通俗点,密码是第一把保险锁,而salt则是网站提供的第二把保险锁。

2011年11月1日星期二

关于动态装载dex

Dalvik目前的实现中,每一个dex文件里最多只能有65536个方法引用。为了解决这个问题,有一种办法是把一个dex分成多个dex,其中一个dex作为APK的主dex,而其他的dex保存在assets中,通过DexClassLoader动态装载进来。
但我实际测试下来,发现并不实用。通过DexClassLoader装载后,每个类必须使用DexClassLoader.loadClass()取到后才能实例化。而代码中有很多使用new实例化的对象,这些类是系统的PathClassLoader来装载,仍然会抛出ClassNotFound异常。而系统的ClassLoader是无法被替换的。
所以看来只好等Google的Dalvik的更新了。

tip:
1. Android的ClassLoader一般是PathClassLoader,PathClassLoader的父classloader是BootClassLoader.
2. when are classes loaded? There are exactly two cases: when the new bytecode is executed (for example, FooClass f = new FooClass();) and when the bytecodes make a static reference to a class (for example, System.out).

2011年10月31日星期一

mistaken usage of a core class

Android工程在编译生成dex文件时dx有时候会出现下面的错误信息:
2.2-froyo中是
trouble processing "javax/Foo.class":
Attempt to include a core class (java.* or javax.*) in something other than a core library.......

2.3-gingerbread中是
trouble processing "javax/Foo.class":
Ill-advised or mistaken usage of a core class (java.* or javax.*)
when not building a core library.

原因是从安全性和完整性考虑,Android(Java有吗?)不允许从外部引用Java的核心库(java.*或javax.*)。更详细的解释参考http://code.google.com/p/android/issues/detail?id=13084#c2
但其实并不是所有的javax.*都不允许。dx的代码com/android/dx/command/dexer/Main.java中,保存了一个“黑名单”来过滤javax的包。

private static final String[] JAVAX_CORE = {
       "accessibility", "crypto", "imageio", "management", "naming", "net",
       "print", "rmi", "security", "sound", "sql", "swing", "transaction",
       "xml"
   };

那么如果Android并没有提供某些核心库而又必须要使用到这些库的情况下,该如何处理呢?一般来说都是通过repackage来重命名包。
1. 有源码的情况下,可以直接修改源代码。(通过ecllipse的改名重构是一个很好的方法)
2. 如果使用的第三方的jar包,则可以通过工具jarjar进行repackage。

2011年10月27日星期四

Android framework注册native方法流程

Android framework有许多使用JNI的地方,但与一般的应用程序注册方法有所不同,framework中通过startReg()统一进行注册。startReg()函数的实现在AndroidRuntime.cpp。
startReg()调用register_jni_procs(gRegJNI, NELEM(gRegJNI), env)。其中 gRegJNI是一个数组,保存各个java类对应的native犯法注册函数的指针。

以BinderProxy为例:
native方法的注册函数是android_util_Binder.cpp的register_android_os_Binder(),这个函数保存在gRegJNI中。经过层层调用后,最终使用jni的RegisterNatives()来完成注册。
android_util_Binder.cpp的register_android_os_Binder() --->
android_util_Binder.cpp的int_register_android_os_BinderProxy() --->
AndroidRuntime::registerNativeMethods() --->
JNIHelp.c的jniRegisterNativeMethods() --->
jni的RegisterNatives()

RegisterNatives所需要的参数是静态变量保存:
android_util_Binder.cpp中,
char* kBinderProxyPathName保存类名
JNINativeMethod gBinderProxyMethods[]保存类中方法的名字、signatures、native方法的指针。

2011年10月20日星期四

Function Object

Function Object(函数对象)顾名思义,就是用法上类似函数,但语法上来说,仍然是一个对象。
相对于函数指针,Function Object有2个优点:
1. 可以保存状态。作为一个对象,Function Object像普通的对象一样可以通过成员保存状态。
2。可以作为模板参数。

C++中,重载了operator()的类实例化的对象就是一个Function Object
例子:
class Sum { 		int val; 	public: 		Sum(int i) :val(i) { } 		operator int() const { return val; }		// extract value  		int operator()(int i) { return val+=i; }	// application 	};  	void f(vector v) 	{ 		Sum s = 0;	// initial value 0 		s = for_each(v.begin(), v.end(), s);	// gather the sum of all elements 		cout << "the sum is " << s << "\n"; 	 		// or even: 		cout << "the sum is " << for_each(v.begin(), v.end(), Sum(0)) << "\n"; 	} 
}

2011年7月31日星期日

[转]where are the apps stored when i use apps2sd?

where are the apps stored when i use apps2sd?

4o66 wrote:
Short answer: Each app stored in /mnt/asec/[appname] is actually stored in an individual encrypted virtual device file

Long answer: (you knew it was coming...)

From a terminal program (or adb, I normally just hop into ConnectBot), if you run "mount", you will see a few lines like so:

/dev/block/dm-[number] /mnt/asec/[app name] vfat ro,dirsync,nosuid,nodev,noexec,relatime,uid=.....

The main thing to pay attention to here is the first two blocks of text.
The first is WHAT is mounted, the second is WHERE it is mounted TO.

In this case, the device known as /dev/block/dm-[number] is referring to a DM (Device Mapper). In linux, this is normally used for either RAID devices or encrypted volumes.

So what is happening is this: To stop the average user from copying and app to sd, then giving it to a friend, they place it in a virtual hard drive, which is encrypted and stored as a file, in a linux partition on the sd card.

Picture like this:

[SD CARD]
[FAT32]
Files you see on the card
[END FAT32]
[EXT4 Linux]
apps2sd files
virtual hard drive file
[DM device (encrypted)]
apk files
[END DM]
[END EXT4]
[END SD CARD]

Now, if you are rooted, this doesn't really stop you. But most users will never know, or care, about rooting their device. They won't even see the EXT partition on their computer if they were to take the sd card out and plug it right in (Windows can't read EXT partitions without some special software). If the user has linux, they will see the files, but the crypto keys are stored in phone protected memory, accessible only to root.

This keeps casual copying from occurring.
Remember this, a lock only keeps and honest man honest.
If I have physical possession of your device, no matter what security you put on it, I will eventually be able to get what I want out of it.

2011年7月25日星期一

EMU是什么单位

EMU英文全称是English Metric Units,在微软的Office Open XML’ DrawingML使用。

以下文字摘抄自维基百科:
A DrawingML graphic's dimensions are specified in English Metric Units (EMUs). It is so called because it allows an exact common representation of dimensions originally in either English or Metric units. This unit is defined as 1/360,000 of a centimeter and thus there are 914,400 EMUs per inch, and 12,700 EMUs per point. This unit was chosen so that integers can be used to accurately represent most dimensions encountered in a document. Floating point cannot accurately represent a fraction that is not a sum of powers of two and the error is magnified when the fractions are added together many times, resulting in misalignment. As an inch is exactly 2.54 centimeters, or 127/50, 1/127 inch is an integer multiple of a power-of-ten fraction of the meter (2×10−4 m). To accurately represent (with an integer) 1 μm = 10−6 m, a divisor of 100 is further needed. To accurately represent the point unit, a divisor of 72 is needed, which also allows divisions by 2, 3, 4, 6, 8, 9, 12, 18, 24, and 36 to be accurate. Multiplying these together gives 127×72×100 = 914,400 units per inch; this also allows exact representations of multiples of 1/100 & 1/32 inch. According to Rick Jelliffe, programmer and standards activist (ISO, W3C, IETF), EMUs are a rational solution to a particular set of design criteria.[20]

另外还有一篇文章解释了为什么使用EMU。

2011年4月16日星期六

拷贝函数使用其他类的protected/privte成员

从写C++开始,我就没搞明白过为什么拷贝构造函数里可以直接使用其他类的protected/privte成员,今天终于得到了答案

发信人: ilovecpp (cpp), 信区: CPlusPlus
标 题: Re: 为什么子类不能访问父类的protected变量?
发信站: 水木社区 (Fri Mar 25 10:07:25 2011), 站内

【 在 RoachCock (我的饭盒我的饭) 的大作中提到: 】
: 这个限制很无聊,和可访问同类型其他对象私有成员的设计矛盾。C++
: 的访问控制应该全是类级别而不是对象级别的。

你看见的这个不协调感其实不是一个孤立事件,而是由于C++试图把
Abstract Data Type (ADT)和object两种概念(甚至还包括C
struct)统一在class这一个框架下,由此带来的诸多矛盾和复杂
性之一。

关于ADT v.s. object,参见:
On Understanding Data Abstraction, Revisited.
William R. Cook. University of Texas at Austin
http://citeseerx.ist.psu.edu/viewdoc/download?
doi=10.1.1.150.3462&rep=rep1&type=pdf

简言之,对于ADT和object,对象的内部结构都对用户隐藏。但是
ADT要求程序里一个类型的所有对象有相同的内部结构,从而不必对
定义在此类型上的操作隐藏。映射到C++,这就是"private是class
scoped"。学过其他OOPL的人对此常有疑问,答案是这个设计并非
源自OOP,而是源自ADT。D&E上讲C++的原型没有virtual function,
那么很可能Stroustrup最早引入class时,他的理解更接近ADT而
不是object。

而对于object,对象的内部结构在对象之外都不可见,包括同类的
对象。Protected只是让对象A的蓝图(父类)可以被对象B的蓝图
(子类)复用,而不能打破OOP的核心教条:"对象的内部结构对外
隐藏"。

所以private和protected的不协调是因为它们来自不同的数据抽象。
这一冲突在class里一再重演:
* 成员函数缺省应该non-virtual还是virtual
* 变量/数据成员应该是value还是reference语义