[ Content | Sidebar ]

Archives for 一月, 2011

给力的翻译

一不小心发错地方了。。就放这吧
————
screenshot_109.png

———–
post by Email~

消灭referer

看到一篇《浅谈WAP网站安全》的文章。里面讲到通过URL的referer获取用户的登录session。
简单描述一下:
例如有个WAP页面: http://abc.com/link.php?sid=xxxxxx,sid为用户登录后的session ID,页面中有链接到http://efg.com的A标签。

当用户点击链接访问http://efg.com时,efg.com的服务器log里就会有类似
xxx.xxx.xxx.xxx – - [17/Jan/2011:13:29:14 +0800] “GET / HTTP/1.0″ 302 20 “http://abc.com/link.php?sid=xxxxxx” “Firefox”
的记录,无疑efg.com就可以得到该用户的在abc.com的登录session

疑问:abc.com傻b吗?不会把sid存到cookie里吗?

全是中国移动的错,虽然现在几乎所有的手机浏览器都支持cookie,但是如果用户通过CMWAP连接上网,浏览器cookie会被网关过滤。所以国内的WAP网站一般会采取URL参数的形式在页面间传递session id;(那二般是什么?二般是CMWAP网关直接把用户的手机号告诉你,当然这中间必然有某些利益)

那么解决方法就是:
1. 不要在这个外链页面加sid,但是显然不可能,sid丢失之后这个用户就相当于登出了
2. 想办法跳转时不带referer

我们只能选方法2,页面跳转有三种方式:
1. 302/301跳转

header('location: http://xxx');
Copy Code 

2. meta标签跳转

<meta http-equiv="refresh" content="2;url=http://xxxx" />
Copy Code 

3. javascript跳转

document.location = 'http://xxxx';
Copy Code 

第三种方法,通过JS跳转对于WAP网站来说显然是不靠谱的。所以我只测试了前面两种方法:
test.php -> test2.php -> test3.php
test.php有一个A标签连接到test2.php,test2.php通过302或meta标签的方式跳转到test3.php
然后分析server log,得到下面的referer字段分析表;

点击页URL = test.php
跳转页URL = test2.php

Location跳转 Meta跳转
UCWEB(S60) 跳转页URL
UCWEB(Anriod) 点击页URL
Opera(S60) 点击页URL 跳转页URL
S60自带浏览器 点击页URL 跳转页URL
Anriod自带浏览器 点击页URL 跳转页URL

结果表明302跳转显然是不靠谱的,对于meta跳转,有的浏览器干脆不传referer,要么直传了跳转页的URL,所以使用meta跳转的方式现在看来还是安全的

为啥说现在看来是安全的:
1 . 因为一个浏览器通过跳转不传referer貌似被认为是不规矩的,看这里http://www.w3help.org/zh-cn/causes/CH9004
2 . 手机浏览器五花八门,我的测试不充分

———–
post by gmail~

PPJ回忆录

个人以为:学一门脚本很容易,但是学几门就是一个痛苦的事,因为我经常把他们搞混。。

于是我下决心写一个能够帮我理清楚的文档,我命之为《PPJ回忆录》,从周5写到今天,精疲力尽,剩下OO和正则部分没写,我决定先歇会~

毫不客气的说,对于同时学里面任意两门语言的同学,这个文档都会对你有帮助。

———–
post by gmail~

topcoder INV 2001 R1 1000 points

上周的某天,我发现了topcoder这个东西,为了了解一下我的算法到底有多差,我决定撞撞。注册,下载客户端之后杯具的发现java,c++,c#,python我就会一个python,还灰色的不能用。于是整了本c++ primer,起床看到睡觉通读了400多页,好书!

我点开inv 2001 R1房,200,500分很轻松,1000 points用到拓扑排序,我买的一本实用算法只讲到树,为此我特地买了一本数据结构,研读之后搞定。。

感觉自己算法确实很菜,继续努力..

Problem Statement
    
***Note: Please keep programs under 7000 characters in length. Thank you

Class Name: Prerequisites
Mathod Name: orderClasses
Parameters: String[]
Returns: String[]

You are a student at a college with the most unbelievably complex prerequisite
structure ever. To help you schedule your classes, you decided to put together
a program that returns the order in which the classes should be taken.

Implement a class Prerequisites which contains a method orderClasses. The
method takes a String[] that contains the classes you must take and returns a
String[] of classes in the order the classes should be taken so that all
prerequisites are met.

String[] elements will be of the form (and TopCoder will ensure this):
“CLASS: PRE1 PRE2 …” where PRE1 and PRE2 are prerequisites of CLASS. CLASS,
PRE1, PRE2, … consist of a department name (3 or 4 capital letters, A-Z
inclusive) followed by a class number (an integer between 100 and 999,
inclusive). The department name should be immediately followed by the class
number with no additional characters, numbers or spaces (i.e. MATH217). It is
not necessary for a class to have prerequisites. In such a case, the colon is
the last character in the String.

You can only take one class at a time, therefore, use the following rules to
determine which class to take :
1) Any prerequisite class(es) listed for a class must be taken before the class
can be taken.
2) If multiple classes can be taken at the same time, you take the one with the
lowest number first, regardless of department.
3) If multiple classes with the same number can be taken at the same time, you
take the department name which comes first in alphabetical order.
4) If the inputted course schedule has errors, return a String[] of length 0.
There is an error if it is impossible to return the classes in an order such
that all prerequisites are met, or if a prerequisite is a course that does not
have its own entry in the inputted String[].

Examples of valid input Strings are:
“CSE111: CSE110 MATH101″
“CSE110:”

Examples of invalid input Strings are:
“CS117:” (department name must consist of 3 – 4 capital letters, inclusive)
“cs117:” (department name must consist of 3 – 4 capital letters, inclusive)
“CS9E11:” (department name must be letters only)
“CSE110: ” (no trailing spaces allowed)
“CSE110: CSE101 ” (no trailing spaces allowed)
“MATH211: MAM2222″ (class number to large)
“MATH211: MAM22″ (class number to small)
“ENGIN517: MATH211″ (department name to large)

Here is the method signature (be sure your method is public):
String[] orderClasses(String[] classSchedule);

TopCoder will make sure classSchedule contains between 1 and 20 Strings,
inclusive, all of the form above. The Strings will have between 1 and 50
characters, inclusive. TopCoder will check that the syntax of the Strings are
correct: The Strings will contain a valid class name, followed by a colon,
possibly followed by a series of unique prerequisite classes separated by
single spaces. Also, TopCoder will ensure that each class has at most one
entry in the String[].

Examples:
If classSchedule={
“CSE121: CSE110″,
“CSE110:”,
“MATH122:”,
}
The method should return: {“CSE110″,”CSE121″,”MATH122″}

If classSchedule={
“ENGL111: ENGL110″,
“ENGL110: ENGL111″
}
The method should return: {}

If classSchedule=[
"ENGL111: ENGL110"
}
The method should return: {}

If classSchedule={
"CSE258: CSE244 CSE243 INTR100"
"CSE221: CSE254 INTR100"
"CSE254: CSE111 MATH210 INTR100"
"CSE244: CSE243 MATH210 INTR100"
"MATH210: INTR100"
"CSE101: INTR100"
"CSE111: INTR100"
"ECE201: CSE111 INTR100"
"ECE111: INTR100"
"CSE243: CSE254"
"INTR100:"
}
The method should return:
{"INTR100","CSE101","CSE111","ECE111","ECE201","MATH210","CSE254","CSE221","CSE2
43","CSE244","CSE258"}
Definition
    
Class:
Prerequisites
Method:
orderClasses
Parameters:
String[]
Returns:
String[]
Method signature:
String[] orderClasses(String[] param0)
(be sure your method is public)
    

This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.

#include <iostream>
#include <string>
#include <algorithm>
#include <list>
#include <vector>
#include <stack>
 
using namespace std;
 
 
 
class ClassObj
{
public:
    string class_name;
    string class_id;
    list<ClassObj> deps;
 
    ClassObj(string str)
    {
        int i = 0;
        for (;i < str.size(); i ++)
            if (str[i] >= '0' && str[i] <= '9') break;
        class_name = str.substr(0, i);
        class_id = str.substr(i, str.size() - i);
    }
 
    void add_dep(const ClassObj &c)
    {
        deps.push_back(c); 
    }
 
    bool has_dep()
    {
        return deps.size() != 0; 
    }
 
};
 
typedef list<ClassObj> ClassList;
 
bool operator < (const ClassObj &c1, const ClassObj &c2)
{
   if (c1.class_id < c2.class_id)
       return true;
   if (c1.class_id == c2.class_id)
       return c1.class_name < c2.class_name;
   return false;
}
 
bool operator == (const ClassObj &c1, const ClassObj &c2)
{
    return c1.class_name == c2.class_name && c1.class_id == c2.class_id;
}
 
 
struct OLGraphArcBox
{
    int tailvex, headvex;
    OLGraphArcBox(int t, int h)
        :tailvex(t), headvex(h){}
};
 
typedef list<OLGraphArcBox> OLGraphArcBoxList;
 
struct OLGraphVexNode
{
    OLGraphArcBoxList inlist, outlist;
    virtual ~OLGraphVexNode(){}
};
 
 
struct ClassGraphNode: public OLGraphVexNode
{
    ClassObj class_obj;
    ClassGraphNode(const ClassObj &clas)
        :class_obj(clas)
    {
    }
};
 
 
typedef vector<OLGraphVexNode *> OLGraphVexNodeList;
 
class OLGraph {
public:
    OLGraphVexNodeList vlist;
    int arcnum;
 
    OLGraph():arcnum(0){}
    virtual ~OLGraph()
    {
        OLGraphVexNodeList::iterator it = vlist.begin();
        for (;it != vlist.end(); it++)
        {
            delete (*it); 
        }
    }
 
    int arcNum()
    {
        return arcnum;
    }
 
    int nodeNum()
    {
        return vlist.size();
    }
 
 
    bool addArc(int ti, int hi)
    {
        if (ti < 0 || ti >= nodeNum() || hi < 0 || hi >= nodeNum() ) return false;
        OLGraphArcBox box(ti, hi);
        vlist[ti]->outlist.push_back(box);
        vlist[hi]->inlist.push_back(box);
        ++ arcnum;
        return true;
    }
 
    void appendNode(OLGraphVexNode *vex)
    {
        vlist.push_back(vex); 
    }
 
    bool topoSort(vector<int> &sort_rt)
    {
        OLGraphVexNodeList::iterator it = vlist.begin(); 
        stack<int> node_stack;
        vector<int> in_list(vlist.size());
 
        for (int i = 0;it != vlist.end(); i ++, it ++)
        {
            in_list[i] = (*it)->inlist.size();
            if (in_list[i] == 0) 
                node_stack.push(i);
        }
 
 
        if (node_stack.size() == 0)
            return false;
 
        while(node_stack.size() != 0)
        {
            int topi = node_stack.top();
            node_stack.pop();
            sort_rt.push_back(topi);
            OLGraphArcBoxList::iterator it2 = vlist[topi]->outlist.begin();
            for(;it2 != vlist[topi]->outlist.end(); it2++)
            {
                int tmpi =  (*it2).headvex;
                if ((-- in_list[tmpi]) == 0) 
                {
                    node_stack.push(tmpi);
                }
            }
 
        }
 
        return true;
    }
 
};
 
bool compArcBox(const OLGraphArcBox &b1, const OLGraphArcBox &b2)
{
    return b1.headvex < b2.headvex;
}
 
class ClassGraph: public OLGraph
{
 
    void sortArcBox()
    {
        for (int i = 0;i < vlist.size(); i ++)
        {
            vlist[i]->outlist.sort(compArcBox); 
        }
    }
 
public:
    ClassGraph(ClassList &clist)
    {
        ClassList::iterator it = clist.begin();
        for (;it != clist.end(); it ++)
        {
            ClassGraphNode *node = new ClassGraphNode(*it);
            appendNode(node);
        }
 
        it = clist.begin();
        for (int hi = 0;it != clist.end(); hi++, it++)
        {
            if (hi != 0 && (*it).has_dep())
            {
                ClassList::iterator it2 = (*it).deps.begin();
                for (;it2 != (*it).deps.end(); ++it2)
                {
                    int ti = getNodeIndex(*it2);
                    if (ti == -1) continue;
                    addArc(ti, hi); 
                }
            }
            else
            {
               addArc(hi - 1, hi);
            }
        }
    }
 
    bool topoSort(vector<int> &sort_rt)
    {
        sortArcBox();
        return this->OLGraph::topoSort(sort_rt);
    }
 
    int getNodeIndex(ClassObj &clas)
    {
        OLGraphVexNodeList::iterator it = vlist.begin();
        for(int i = 0;it != vlist.end(); it++, i++)
        {
            if (((ClassGraphNode *)(*it))->class_obj == clas) 
                return i;
        }
 
        return -1;
    }
 
};
 
class Prerequisites 
{
    public:
    vector<string> orderClasses(vector<string> cs)
    {
        ClassList sorted_cs;
 
        vector<string>::iterator it3 = cs.begin();
 
        for(; it3 != cs.end(); it3 ++)
        {
            string class_str = *it3;
            int start_pos = 0;
 
            for (int j = 0; j < class_str.size(); j ++)
            {
                if (class_str[j] == ':')
                {
                    ClassObj *class_obj;
                    ClassObj tmp_obj(class_str.substr(start_pos, j));
                    class_obj = &tmp_obj;
                    sorted_cs.push_back(tmp_obj); 
 
                    j ++;
                    start_pos = j + 1;
                }
                else if (class_str[j] == ' ' || j == class_str.size() - 1)
                {
                    ClassObj *dep_obj;
 
                    if (class_str[j] == ' ')
                    {
                        dep_obj = new ClassObj(class_str.substr(start_pos, j - start_pos));
                    }
                    else
                    {
 
                        dep_obj = new ClassObj(class_str.substr(start_pos, j - start_pos + 1));
                    }
 
                    sorted_cs.back().add_dep(*dep_obj);
 
                    delete dep_obj;
                    start_pos = j + 1;
                }
            }
        }
 
 
        sorted_cs.sort();
        ClassList::iterator it2 = sorted_cs.begin();
        for (;it2 != sorted_cs.end(); it2++)
        {
            cout << it2->class_name << it2->class_id << endl; 
        }
 
        ClassGraph grp(sorted_cs);
        vector<int> sorted_nodes;
        grp.topoSort(sorted_nodes);
 
        vector<string> rt;
        for(int i = 0;i < sorted_cs.size(); i ++)
        {
            ClassGraphNode *node = (ClassGraphNode *)grp.vlist[i]; 
            cout << node->class_obj.class_name << node->class_obj.class_id << endl; 
            rt.push_back(node->class_obj.class_name + node->class_obj.class_id);
        }
 
        return rt;
    }
};
 
int main()
{
    Prerequisites test;
    vector<string> cs;
    cs.push_back("CSE258: CSE244 CSE243 INTR100");
    cs.push_back("CSE221: CSE254 INTR100");
    cs.push_back("CSE254: CSE111 MATH210 INTR100");
    cs.push_back("CSE244: CSE243 MATH210 INTR100");
    cs.push_back("MATH210: INTR100");
    cs.push_back("CSE101: INTR100");
    cs.push_back("CSE111: INTR100");
    cs.push_back("ECE201: CSE111 INTR100");
    cs.push_back("ECE111: INTR100");
    cs.push_back("CSE243: CSE254");
    cs.push_back("INTR100:");
    test.orderClasses(cs);
}
Copy Code 

———–
post by gmail~

unamed

转一个牛人的经验贴
—————
发信人: SlutteryWolf (一生懸命|情色·猥琐·变态·双子狼), 信区: Python
标 题: Tornado的实现还是很强大的
发信站: 水木社区 (Wed Jan 5 13:19:28 2011), 转信

这段时间自己把iostream.py实现了一下,顺便给socket打了个补丁,发现了好几个
有趣的点:

1. socket的C实现中,对于recv函数,直接返回新生成的字符串比传入缓冲区写还要
快。 大概能快10%。代码稍后附上,大家可以自由cProfile (./python -m
cProfile yourcode.py)。

2. Python的速度大大逊于原生代码。
用cProfile做了些调优后的感想。不过大家用Python都是冲着顺手易用去的,所以这
一点倒也无可厚非。

3. Python的List(含string)操作是高度优化过的。
我曾经试图用自己管理的bytearray缓冲区来替代原生的string,因为源代码里面包
括了大量的+=和区段赋值操作,以提高性能。
但是我错了,而且错的很离谱。
现在的bytearray1[x:length] = bytearray2[y:length]操作和我自己写的
memcpy(bytearray2, y, bytearray1, x, length)几乎一样快。
而且如果是反复调用string_a += random_string_b,并不会每次重新分配内存并做
拷贝操作,和预先分配一块内存做搬运基本一样快。

4. 函数调用在Python里面的开销是不小的。对于较为关键的代码,建议手工
inline。当然如果对性能要求再高建议直接C.

5. 用 not not collection_var 来代替 len(collection_var) > 0 的判断语
句。

6. 对于deque,访问deque.popleft,然后根据判断再deque.appendleft,比直接
deque[0]要快。

总之,Tornado的实现考虑到了以上中的大部及重点,如1和3. 它的实现蛮强大,大家
放心使用。。。

———–
post by gmail~