Website Tour with jQuery

http://tympanus.net/codrops/2010/12/21/website-tour/

常用的软件保护技术

软件保护是为了保护软件不被破解,不被盗版,充分保护开发者的利益。下边我尽量以浅显易懂的语言一一介绍目前流行的软件保护技术,并分析各自的特点。

1.   注册码技术

  这是一般共享软件所常用的保护技术,当用户从网络上下载某个共享软件后,一般都有使用时间或功能上的限制,如果想使用正式版,你必须进行注册。注册过程一般是用户掏过钱且把自己的信息(例如用户名等)告诉给软件公司,软件公司会根据用户信息计算出一个注册码(或授权文件),在用户得到这个注册码后,按照注册需要的步骤在软件中输入注册信息和注册码,其注册信息的合法性由软件验证通过后,软件就会取消掉本身的各种限制。在互联网上的软件80%都是以这种方式来保护的,国内http://www.sharebank.com.cn/就是提供共享软件注册服务的一个平台。
      优点:实现起来简单,成本较低,用户购买非常方便
      缺点:
            1. 不能有效防止一号多用的情况 (除了根据机器ID计算注册码的情况)
            2. 安全系数一般, 因为理论上验证程序一旦被cracker解密,则可以很容易地做出注册机,或是直接修改汇编指令跳过验证程序。

2.   序列号技术

     这是很多光盘发行的软件所采用的保护技术,在发行光盘上会提供一个正版序列号,在安装过程中用户输入正确的序列号后才可安装成功。常见的MS-Office就是使用这种保护方式的。
      优点:实现起来简单,成本较低,销售模式简单
      缺点:
             1. 在安装时很难检测一号多用,想想到处盗版的Office就知道了。
             2. 采用这种方式的安装程序一般自身会携带一个密钥库,理论上是可以被破解的。

3.   加密狗

      加密狗是一种复杂的软硬件技术结合在一起的加密工具。软件在插入加密狗的机器上才能运行,例如我在使用建行网银交易时必须插入建行U盾,这个U盾实际上就是一个加密狗。真正有商业价值得软件一般都用加密狗来保护。
      优点:很安全,破解难度相当高
      缺点:
             1. 开发成本和硬件成本相当高,最普通的加密狗也要上百元
             2. 使用不方便,想使用时还必须插入一个加密狗

4.   联机验证
      这种技术是为了弥补序列号或注册码技术的不足而诞生的,例如为了防止一号多用,可在注册时或运行时不定时通过服务器端验证是否合法授权,是否存在一号多用的嫌疑。现在的授权管理的行业标准解决方案多数是基于此,例如RosettaStone、ProE、AutoCAD都是使用Flexnet Publisher的解决方案。
      优点: 较注册码和序列号方式安全,可灵活定制授权模式(浮动模式和命名用户模式等)
      缺点:
              1. 需要网络和服务端支持
              2. 和服务端通信的通道必须是加密的,例如采用SSL

5. 法律保护

      上边几条都是基于技术层面的,最后不得不提一下,法律保护的重要性,在软件里要写明版权声明,最好是申请软件著作权。据说MS在中国的主要收入来源是打击盗版,法律保护的重要性,你懂的!

[zz] How to interview a programmer?

一、提问之前的准备

首先,最重要的是,你自己一开始就应该想清楚:

  1. 需要新员工完成什么样的任务?

  2. 怎样的人能完成这样的任务?

  3. 哪些途径和方法可以发现这样的人?

只有明确这些根本性的问题,才能正确高效地完成面试。

二、提问的原则

假定你对上一节的三个问题,已经有了清晰的想法,那么接下来就可以设计如何提问了。

有一些提问的原则,是你应该遵循的:

  * 每一个面试问题都有明确的目的。你不仅自己了解,还能向其他面试官解释清楚。

  * 多提一些开放性(Open-ended)的问题,而不是那种用Yes/No就可以回答的问题。这样做使你有机会与面试者展开讨论,并且提出后续的问题,尽可能多地了解对方。

  * 不要问宗教、家庭、健康、个人隐私等方面的问题。

  * 不要问太复杂的问题。因为面试者没有太多思考时间,所以无法周全地回答,你也就无从判断他的能力了。

三、考察专业能力

为了确认面试者是胜任的,你可以问一些与职位相关的专业方面的问题。(不过通常来说,一次面试不足以看出一个人的专业能力。)

比如,你的招聘职位是系统管理员,你可以问”如何快速地在50台机器上部署Linux?”(提示:正确答案不是刻录50张安装光盘。)

另外,你还应该向面试者了解他的过去,因为过去是未来的最好预测依据。不过,提问的重点不要仅仅是他过去的成果,更要关注在当时的环境中,他是如何决策和实施的。

四、考察综合素质

因为人是会发展的,所以某种程度上,面试者的综合素质要比他的专业能力更重要。

所以,具体的技术问题(如何调用API、什么是设计模式、编程语言的语法等等)可以少问一些,更应该关注面试者的事业心、对工作的热情、进取心、自律能力、毅力等方面。

下面是一些典型问题:

  Why did you get into development?
  你为什么开发软件?

  How many technical books did you read in the past year?
  去年你读了几本技术书籍?

  What was your favorite technical book in the past year? What did you learn from it?
  去年你最喜欢的技术书籍是哪本?你从中学到了什么?

  What websites do you read regularly, related to development?
  平时你经常访问哪些编程类网站?

  Do you maintain any open-source projects?
  你有自己的开源项目吗?

  Do you code in your spare-time?
  业余时间你编程吗?

  Do you love programming, or do you do it for the money?
  对于你来说,编程是一种爱好,还是一种谋生手段?

  Have you accomplished anything important in your career yet? Do you want to?
  你的职业生涯之中有什么重要的成就?它是你主导的吗?

  What would make you feel that you have done something important?
  什么事情会让你很有成就感?

五、考察理性思维

某些情况下,你可能需要了解面试者的分析判断能力,看他能否全面地思考问题、客观地评价自己。

那么,你可以依次提出这样三个问题:

  What’s your favorite programming language? Why?
  你最喜欢的编程语言是哪种?为什么?

  If you could add one feature to your favorite language, what would it be? Why?
  如果允许你为这种语言加一种功能,你会加什么功能?为什么?

  If you could remove one feature from it, what would it be? Why?
  如果允许你取消一种功能,会是什么功能?为什么?

这里的重点是,让面试者从正反两方面评价一件自己熟悉的东西,看看他的思维是否片面。答案无所谓对错,只要面试者有一个明确的立场,能够从正反两方面说出令人信服的理由,就可以了。比如,某个软件的口碑不好,但是面试者说他很喜欢,而且说得出一大堆理由,清楚地解释了这种软件的优点和缺点在哪里,这样就很好。

你还可以把这些问题,套用在其他东西上面,比如操作系统、文字编辑器等等。

原文链接:http://www.ruanyifeng.com/blog/2010/12/how_to_interview_a_programmer.html

在ActionScript Virtual Machine 上运行C/C++代码

Alchemy is a research project that allows users to compile C and C++ code that is targeted to run on the open source ActionScript Virtual Machine (AVM2). The purpose of this preview is to assess the level of community interest in reusing existing C and C++ libraries in Web applications that run on Adobe® Flash® Player and Adobe AIR®.

http://labs.adobe.com/technologies/alchemy/

加速你的Hibernate引擎

引两篇博文:
http://www.infoq.com/cn/articles/hibernate_tuning
http://www.infoq.com/cn/articles/hibernate_tuning-ii

How to traverse resource directory in java?

最新版本的jdk 1.6 里访问resource的功能依然有限,只有class.getResource(name)和class.getResourceAsStream(name)两个方法。实际使用中这两个方法肯定不够用。在此提供一个遍历resource目录的方法。
原理很简单:
1. 未制作成jar包前,资源位于target/classes目录下,这时遍历目录即可
2. 如果已经制作成jar包,资源位于jar包里,枚举当前JarFile即可

public static List<File> enumerateDir(File dir) {

    List<File> fileList = new ArrayList<File>();
    if (dir == null) {

    } else if (dir.isDirectory()) {

        File[] subFiles = dir.listFiles();

        for (File subFile : subFiles) {

            fileList.add(subFile);
            if (subFile.isDirectory()) {
                fileList.addAll(enumerateDir(subFile));
            }

        }

    } else {
        fileList.add(dir);
    }

    return fileList;
}

 

/**
     * get resources by regular name. it works for files and also jars, and it’s
     * compatible with WINDOWS and LINUX
     *
     * @author aaashun
     * @param clazz
     *            any java class that lives in the same place as the resources
     *            you want.
     * @param name
     *            you can use REGEX, not start with ‘/’.
     * @return name of each resource, NOTE: folder will not be included
     * @throws IOException
     */
    @SuppressWarnings(“unchecked”)
    public static String[] getResources(Class clazz, String name) throws IOException {

        Set<String> resources = new HashSet<String>();

        String classResourceName = clazz.getName().replace(“.”, “/”) + “.class”;
        URL classResourceURL = clazz.getClassLoader().getResource(classResourceName);
        String classResourcePath = classResourceURL.getPath();

        if (classResourceURL.getProtocol().equals(“file”)) {

            // 开发环境里class和resource同位于target/classes目录下
            String classesDirPath = classResourcePath.substring(classResourcePath.indexOf(“/”) + 1, classResourcePath
                    .indexOf(classResourceName));
            File classesDir = new File(classesDirPath);

            List<File> files = enumerateDir(classesDir);
            for (File file : files) {

                String resourceName = file.getAbsolutePath();
                resourceName = resourceName.substring(classesDirPath.length());
                resourceName = resourceName.replace(“\\”, “/”);
                if (!file.isDirectory() && resourceName.matches(name)) {
                    resources.add(resourceName);
                }

            }

        } else if (classResourceURL.getProtocol().equals(“jar”)) {

            // 打包成jar包时,class和resource同位于jar包里
            String jarPath = classResourcePath.substring(classResourcePath.indexOf(“/”), classResourceURL.getPath()
                    .indexOf(“!”));

            try {

                JarFile jarFile = new JarFile(URLDecoder.decode(jarPath, “UTF-8″));
                Enumeration<JarEntry> jarEntries = jarFile.entries();

                while (jarEntries.hasMoreElements()) {

                    JarEntry jarEntry = jarEntries.nextElement();
                    String resourceName = jarEntry.getName();
                    if (resourceName.matches(name) && !jarEntry.isDirectory()) {
                        resources.add(resourceName);
                    }

                }

            } catch (UnsupportedEncodingException e) {
                // ignore
            }

        }

        return resources.toArray(new String[0]);

    }

Maven中使用第三方jar包

如果第三方jar不在repository中,则有如下两种方法使用它:
1. 使用system scope

        <dependency>
          <groupId>org.dyno.visual.swing.layouts</groupId>
          <artifactId>grouplayout</artifactId>
          <version>1.0</version>
          <scope>system</scope>
          <systemPath>……………</systemPath>
       </dependency>

    不过不推荐此方法,因为在使用maven-assembly-plugin打包jar时不能将这第三方jar放到目标jar里

2. 安装此第三方向jar到本地repository

    mvn install:install-file -Dfile=FILEPATH -DgroupId=GROUPID -DartifactId=ARTIFACTID -Dversion=1.0 -Dpackaging=jar -DgeneratePom=true

    如果不知道groupId或artifactId,可以随便填一个。安装好后就可以很方便使用了。

汇编学习笔记1

一、计算机组成

    计算机由运算器、控制器、存储器、输入设备、输出设备组成。

    1. 运算器:
        a. 由算术逻辑单元ALU(arithmetic logic unit)、累加器、状态寄存器、通用寄存器组等构成
        b. 运算器的操作和操作种类由控制器决定
        c. 运算器处理的数据来自存储器;处理后的结果数据通常送回存储器,或暂时寄存在运算器中
        d. 和控制器共同组成CPU

    2. 控制器:
        a. 负责从存储器中取出指令,并对指令进行译码;根据指令的要求,按时间的先后顺序,负责向其它各部件发出控制信号,保证各部件协调一致地工作,一步一步地完成各种操作。
        b. 由指令寄存器IR(InstructionRegister)、程序计数器PC(ProgramCounter)、操作控制器0C(OperationController)和译码器等部件组成。

    3. 存储器:分为外存和内存

    4. 输入设备:键盘、鼠标等

    5. 输出设备:显示器、耳机等

二、 寄存器

    8086有14个16位寄存器,类别是通用寄存器、指令指针、标志寄存器、段寄存器。

    1. 通用寄存器:分为数据寄存器(4个)和指针寄存器及变址寄存器(4个)两组
        a. 数据寄存器又分为:
            AH&AL=AX(accumulator register):累加寄存器,常用于运算;在乘除等指令中指定用来存放操作数,另外,所有的I/O指令都使用这一寄存器与外界设备传送数据
            BH&BL=BX(base register):基址寄存器,常用于地址索引
            CH&CL=CX(counter register):计数寄存器,常用于计数;常用于保存计算值,如在移位指令,循环(loop)和串处理指令中用作隐含的计数器
            DH&DL=DX(data register):数据寄存器,常用于数据传递
        b. 指针寄存器和变址寄存器包括:
            SP(stack pointer):堆栈指针,与SS配合使用,可指向目前的堆栈位置
            BP(base pointer):基址指针寄存器,可用作SS的一个相对基址位置
            SI(source index):源变址寄存器可用来存放相对于DS段之源变址指针
            DI(destination index): 目的变址寄存器,可用来存放相对于 ES 段之目的变址指针

    2. 指令指针:指令指针IP(instruction pointer)是一个16位专用寄存器,它指向当前需要取出的指令字节,当BIU从内存中取出一个指令字节后,IP就自动加1,指向下一个指令字节。注意,IP指向的是指令地址的段内地址偏移量,又称偏移地址(Offset Address)或有效地址(EA,Effective Address)。

    3. 标志寄存器:8086有一个18位的标志寄存器FR,在FR中有意义的有9位,其中6位是状态位,3位是控制位。
        OF
        DF
        IF
        TF
        SF
        ZF:零标志ZF用来反映运算结果是否为0。如果运算结果为0,则其值为1,否则其值为0。
        AF
        PF
        CF

    4. 段寄存器:为了运用所有的内存空间,8086设定了四个段寄存器,专门用来保存段地址。当一个程序要执行时,就要决定程序代码、数据和堆栈各要用到内存的哪些位置,通过设定段寄存器 CS,DS,SS 来指向这些起始位置。
        CS(code segment):代码段寄存器
        DS(data segment):数据段寄存器
        SS(stack segment):堆栈段寄存器
        ES(extra segment):附加段寄存器

Best Practices for Speeding Up Your Web Site

There are 35 rules from Yahoo!

http://developer.yahoo.com/performance/rules.html

Hello, world!