blog | 业余项目 | 关于Karry | RSS订阅 | 我在阅读 | 管理

Archive for the ‘服务器端’ Category

Python学习笔记(2)

星期五, 九月 4th, 2009
  1. Python中没有 switch case语句,只有if elif else
  2. 字符串、数字、元组是不可变的,改变其值会创建新的对象(这也是为什么大量字符串的拼接会导致效率降低的原因)
  3. 字符串模版(直觉是这个功能做WEB的时候很有用,可以轻易的实现根据模版生成静态页面的功能):
    from string import Template
    s = Template("There are ${test}")
    print s.substitute(test="python")  ==>输出 There are python 
    substitute中参数如果没有对应声明字符串模版中的
    Template 对象还有另外一个方法save_substitute(),该方法在没有声明key的情况下不会报错,直接输出
  4. 浅拷贝与深拷贝
    在拷贝一个列表时,有两种拷贝方式。浅拷贝,就是新创建了一个类型跟原类型一样,其内容是原来对象的引用,也就是说这个拷贝本身是新的,但是它的内容不是。而深拷贝则是建了一个与原对象独立的,但值一模一样的新对象。
    如何实现浅拷贝?
    通常有三种方式,(1)完全的切片操作[:](2)利用工厂函数,比如list(),dict()等。(3)使用copy模块的copy函数。
    a 前拷贝的示例:
    person = ["name",['male',19]]
    girl = person[:]    # 将人这个列表浅拷贝到girl
    boy = person[:]  # 将人这个列表浅拷贝到boy
    gilr[0] = "lily"   #修改名字
    gril[1][0] = "female"
    boy[0] = “john”
    boy[1][0]="male"
    boy[1][1]=22

      例认为打印出girl 和boy结果是什么?
    boy ====>  ["johu",['male',22]]
    girl ====>   ["lily",['male',22]]
    为什么名字相互之间没有影响,而性别和年龄之间有影响呢?这是因为该列表中的第一个元素是一个字符串,是一个不可变的对象,一旦对其修改,就会独立生成一个新的对象。因此当拷贝的时候,字符串被显示的拷贝了,而列表只是拷贝了一个引用。
    那么,如何实现深拷贝
    在copy模块,有一个deepcopy()方法,可以轻松实现深拷贝。

 

Python学习笔记(1)

星期五, 八月 28th, 2009

由于公司的服务器端用的是Python,所以决定抽点时间熟悉一下,也好在以后的工作中能和其他同事有比较好的配合。

我主要是把Python和其他语言(特别是Javascript和c#,因为我熟悉)一些不一样的特性列出来。

首先说一下对Python的大体印象,Python和Javascript一样是解释性的语言,也是弱类型的语言。同时也是面向对象的一种语言,一切皆是对象:甚至字符串,变量,函数,都是对象。Python的设计也非常酷,用起来很灵活,习惯使用Javascript的人,一定会爱上Python 

  1. 没有大括号,靠缩进来控制代码块的开始与结束。语句结束不用分号,但一行中有多个语句,用分号隔开。
  2. // 运算符和 ** 运算符
    //特殊的除法运算(千万别以为是注释代码的,Python的代码注释用#),运算符对整型和浮点型都会取整。如:2.0//3.0=0   **是就幂,如:2**3 表示2的3次方。
  3. 不等号有两种写法 != 和<>
  4. 逻辑操作符的关键字是 and or not
  5. 三引号(三个连续的单引号或者双引号)中的特殊字符自动转义
  6. Python中没有数组,只有列表,但其特性跟js中的数组一样,也就是长度可变的数组。
  7. 列表可以用引号(:)来获取元素
    如:a = [0,1,2,3]   a[1:4] =[1,2,3]   a[:3]=[0,1,2]   a[1:] = [1,2,3]
  8. for 循环就相当于c#中的foreach ,有一个range函数来提供索引.
    #遍历数组
    a = [1,2,3]
    for(item in a):
        print item
    #另外一个例子
    for eachNum in range(3)
        print eachNum

    这里 range(obj1,obj2)为内建函数。obj1不提供默认为0,obj2不提供默认为1,返回一个从obj1到obj2的数组

  9. 可以多元赋值
    x,y= 1,2  等价于  x=1 y=2      x,y = y,x   交换x和y的值(很好很强大,哈哈)
  10. 布尔值为False的对象有
    None(相当于js中的null),False,所有值为0的数,空字符串”(注:’0′为True),空元组(),空列表[],空字典{}
  11. 多个比较操作符可以在同一行中进行
    3<4<5  等同于(3<4 and 4<5)
  12. 用 is 来判断两个变量是否指向同一个对象。
    a is b 等同于id(a) is id(b)      id()是获取对象的内存编号。但是要注意的是 Python为了提高性能会对整型和字符串类型进行缓存。但对浮点型不会。
    例如 a =2 ;b = 2; a is b  返回True,a=2.0;b=2.0 a is b 返回False
  13. 逻辑操作符的优先级 not 高于 and  高于 or
  14. 几个标准内建函数
    type(obj) 获取obj的类型,类似Javascript中的type of
    str(obj) 将obj 转换为 字符串类型
    repr(obj)是奖obj 序列化,转换为字符串,但是可以通过eval()还原,所以obj == eval(repr(obj))
  15. 与Javascript一样,Python 不支持方法和函数的重载(弱类型语言的特点)
  16. 字符串和列表、元组统称为序列,可以进行 in 、not in、+、*操作
    obj in seq  判断obj 元素是否包含在seq中,在返回True,不在返回False
    + 操作符可以把两个序列连接起来。  [1,2,3] +[4,5,6] == [1,2,3,4,5,6]
    * 操作符把一个序列拷贝多分。  [1,2]* 2 == [1,2,1,2]
  17. 列表的下标可以是负数,负数标识从结束点往左找。
    [1,2,3][-2]==2

今天先到这里,未完待续

12/29 更正:感谢butterinsect ,我确实没有弄清楚,python是强类型的语言,确切的说是,python是隐式类型的强类型语言。也就是说,在声明变量的时候,不需要显式说明它的类型,但是在Python里,是有明确的类型的概念,而且不同类型的对象不能相互替代和操作,比如:

>>> 10 + '20'

会出现错误 TypeError: unsupported operand type(s) for +: ‘int’ and ’str’

ASP.NET中如何防SQL注入

星期三, 八月 5th, 2009

防SQL 注入是一个系统工程,在项目开发中就要系统的考虑SQL 注入的问题。一般做到以下4点,能比较好的控制SQL 注入:

  1. 严格验证用户的一切输入,包括URL参数。
  2. 将用户登录名称、密码等数据加密保存
  3. 不要用拼接字符串的方式来生成SQL语句,而是用SQL Parameters 传参数或者用存储过程来查询
  4. 严格验证上传文件的后缀,exe、aspx、asp等可执行程序禁止上传。

这里介绍一个简单通用的方法,用来验证字符串中是否有敏感字符,参数可以是一个字符串,也可以是一个字符串集合,敏感字符可以在Lawlesses数组中定义:

  1.         public static string[] Lawlesses = { "=", "’" };
  2.         /// <summary>
  3.         /// 敏感字符检测
  4.         /// </summary>
  5.         /// <param name="args"></param>
  6.         /// <returns></returns>
  7.         public static bool CheckParams(params object[] args)
  8.         {
  9.             if (Lawlesses == null || Lawlesses.Length <= 0) return true;
  10.             //构造正则表达式,例:Lawlesses是=号和’号,则正则表达式为 .*[=}'].*
  11.             //另外,由于我是想做通用而且容易修改的函数,所以多了一步由字符数组到正则表达式,实际使用中,直接写正则表达式亦可;
  12.             string str_Regex = ".*[";
  13.             for (int i = 0; i < Lawlesses.Length - 1; i++)
  14.             {
  15.                 str_Regex += Lawlesses[i] + "|";
  16.             }
  17.             str_Regex += Lawlesses[Lawlesses.Length - 1] + "].*";
  18.             //
  19.             foreach (object arg in args)
  20.             {
  21.                 if (arg is string)//如果是字符串,直接检查
  22.                 {
  23.                     if (Regex.Matches(arg.ToString(), str_Regex).Count > 0)
  24.                         return false;
  25.                 }
  26.                 else if (arg is ICollection)//如果是一个集合,则检查集合内元素是否字符串,是字符串,就进行检查
  27.                 {
  28.                     foreach (object obj in (ICollection)arg)
  29.                     {
  30.                         if (obj is string)
  31.                         {
  32.                             if (Regex.Matches(obj.ToString(), str_Regex).Count > 0)
  33.                                 return false;
  34.                         }
  35.                     }
  36.                 }
  37.             }
  38.             return true;
  39.         }

 

参考文档:http://msdn.microsoft.com/zh-cn/library/ms998271(en-us).aspx

MSSQL2005 孤立用户的解决方法

星期三, 七月 29th, 2009

 Vinehoo.com近日经常遭到攻击,好几次数据库挂马,前几天把论坛升级了,今天又升级了数据库,把之前的MSSQL 2000 升级到MSSQL 2005,用的是数据库还原功能还原的,遇到了这个帐号孤立的问题。

什么是孤立用户的问题?

比如,以前的数据库的很多表是用户test建立的,但是当我们恢复数据库后,test用户此时就成了孤立用户,没有与之对应的登陆用户名,哪怕你建立了一个test登录用户名,而且是以前的用户密码,用该用户登录后同样没办法操作以前属于test的用户表。

Google 了一下,有很多解决方案,不过很多方案没办法实现,因为MSSQL 2005的权限的关系。这里介绍一个经过我验证的解决方法:

我们在建立了同样名称的数据库登录用户后,数据库中的表我们照样不能使用时因为sid的不同,就是系统登录表和数据库用户表中的用户名相同,单是sid字段,数据库中的还是以前旧系统的sid值,所以我们就要把它对应成我们新建的,数据库靠sid来识别用户。

这里可以使用存储过程sp_change_users_login。它有三种动作,分别是report,update_one和auto_fix。运行下面的代码,系统会列出当前数据库的孤立用户数。sp_change_users_login ‘report’我们只需要选择当前数据库为testdb,然后运行

sp_change_users_login ‘update_one’,'test’,'test’

系统就会提示修复了一个孤立用户。如果没有建立test的登录用户,还可以用

sp_change_users_login ‘Auto_Fix’, ‘test’, NULL, ‘testpassword’

来创建一个登录用户名为test,密码为testpassword的用户与之对应。通常情况下,数据库对象得到访问问题已经解决了。如果有多个数据库中有同一个用户的数据表,只需要选择不同的数据库,执行update_one的那个就行了。

 

vinehoo.com一周岁纪念

星期二, 五月 12th, 2009

vinehoo.com当前状况(不包括论坛bbs.vinehoo.com):

PR值:4

日访问人数: 700

日访问PV:3500

Alexa Traffic Rank :393699

 

 

.Net正则表达式中的特殊字符和转义方式

星期三, 二月 18th, 2009

在.NET Framework 开发人员指南 的 字符转义 一节 有这样一段话。
除 .$ ^ { [ ( | ) * + ? \ 外,其他字符与自身匹配。
但是其中并未注明这些字符应该匹配为什么字符。

点的转义:.  ==> \\u002E
美元符号的转义:$  ==> \\u0024
乘方符号的转义:^  ==> \\u005E
左大括号的转义:{  ==> \\u007B
左方括号的转义:[  ==> \\u005B
左圆括号的转义:(  ==> \\u0028
竖线的转义:| ==> \\u007C
右圆括号的转义:) ==> \\u0029
星号的转义:*  ==> \\u002A
加号的转义:+  ==> \\u002B
问号的转义:?  ==> \\u003F
反斜杠的转义:\ ==> \\u005C

 

操作符 效果
. 匹配任何单个字符。
? 之前的项目是可选的,匹配最多一次。
* 匹配出现零次或者多次的先前项目。
+ 匹配一次或者多次先前项目。
{N} 精确匹配N次先前的项目。
{N,} 先前的项目匹配N或者更多次。
{N,M} 先前的项目匹配至少N次,但是不多于M次。
- 表示范围如果不是列表中最先或者最后或者一个范围的结束点。
^ 匹配行开始的空字符串;也表示不在列表范围内的字符。
$ 匹配行末的空字符串。
\b 匹配词两边的空字符串。
\B 匹配提供的空字符串Matches the empty string provided it’s not at the edge of a word.
\< 匹配任何词开头的空字符串。
\> 匹配任何词结尾的空字符串。

回顾2008,展望2009—vinehoo.com篇

星期二, 一月 20th, 2009

 

回顾:
从2008年年初开始,利用业余时间一点一点的开发出来,是中国第一家葡萄酒为主题的web2.0网站,从零开始,先后发布了葡萄酒百科、葡萄酒搜索、vinehoo策划、酒乡漫步、酒志资讯、城市酒窖等栏目。对葡萄酒相关资源进行收集和整合,整合了GOOGLE MAP API,整合了众多的Jquery插件,整合了国内外众多知名的葡萄酒博客,现在的vinehoo.com(不包括美酒坊论坛)已经是一个日PV近2000,日IP超过400,ALexa排名近70W的葡萄酒社区。
在这一年中,版块在逐步增长,交互模式也在悄然更新。期间走了不少弯路,不断的修改和调整,也在这个过程中学到了不少的东西。

除了功能的增加、界面的修改以外,还对代码的组织进行了重构。前端的代码在慢慢的优化,C#项目文件由一个扩大到了7个,严格按照MVC模型来组织代码。对代码进行了分层,系统的组织了命名空间。限于现在的知识水平和能力,这个结构还有很多不合理的地方,以后会不断的重构,优化代码。但总算是朝好的方向迈出了第一步。

遗憾:

2008年11月,vinehoo.com服务器遭到攻击,被挂了木马,使得google 对vinehoo.com搜录惩罚,在持续一个月的时间里无法从Google 上搜索到vinehoo.com,好在是,很快恢复了正常。

展望:
近几年SNS(Social Networking Services)已经逐渐显现出了威力,2009年的VINEHOO.COM将朝这个方向前进。如果说2008年通过在信息和资源吸引大家来到VINEHOO.COM社区,那么,2009年的目标就是通过SNS,让大家留在VINEHOO.COM社区。同时让参与这个社区的所有人为这个社区作出贡献。

关于ATOM

星期二, 十一月 25th, 2008

这些天在做VINEHOO.COM 的葡萄酒BLOG聚合平台,发现有些BLOG(特别是国外的)采用的是ATOM 格式的订阅方式,到底ATOM是个撒子东东咧?

今天就来看看。

Atom是一对彼此相关的标准。Atom供稿格式(Atom Syndication Format)是用于网站消息来源,基于XML的文档格式;而Atom出版协定(Atom Publishing Protocol,简称AtomPub或APP)是用于新增及修改网络资源,基于HTTP的协议。

它借鉴了各种版本RSS的 使用经验,被许多的聚合工具广泛使用在发布和使用上。Atom供稿格式设计作为RSS的替代品;而Atom出版协定用来取代现有的多种发布方式(如 Blogger API和LiveJournal XML-RPC Client/Server Protocol)。而值得一提的是Google提供的多种服务正在使用Atom。Google Data API (GData) 亦基于Atom。

当初发展Atom的动机在于广泛应用RSS 2.0时所遇到的问题。为了降低开发支持Web聚合应用的难度,下面列出Atom 1.0所克服的RSS 2.0几个主要问题:

  • RSS 2.0 可能包含文本或经过编码的HTML内容,同时却没有提供明确的区分办法;相比之下,Atom 则提供了明确的标签(也就是typed)。
  • RSS 2.0 的 description 标签可以包含全文或摘要(尽管该标签的英文含义为描述或摘要)。Atom 则分别提供了 summary 和 content标签,用以区分摘要和内容,同时 Atom 允许在summary中添加非文本内容。
  • RSS 2.0 存在多种非标准形式的应用,而 Atom 具有统一的标准,这便于内容的聚合和发现。
  • Atom 有符合XML标准的命名空间,RSS 2.0 却没有。
  • Atom 通过XML内置的xml:base标签来指示相对地址(URI),RSS 2.0 则无相应的机制区分相对地址和绝对地址。
  • Atom 通过XML内置的xml:lang,而 RSS 采用自己的language标签。
  • Atom 强制为每个条目设定唯一的ID,这将便于内容的跟踪和更新。
  • Atom 1.0 允许条目单独成为文档,RSS 2.0 则只支持完整的种子文档,这可能产生不必要的复杂性和带宽消耗。
  • Atom 按照RFC 3339标准(ISO 8601标准的一个子集)表示时间 ,而RSS 2.0 中没有指定统一的时间格式。
  • Atom 1.0 具有在 IANA 注册了的 MIME 类型,而 RSS 2.0 所使用的 application/rss+xml 并未注册。
  • Atom 1.0 标准包括一个 XML schema,RSS 2.0 却没有。
  • Atom 是IETF组织标准化程序下的一个开放的发展中标准,RSS 2.0 则不属于任何标准化组织,而且它不是开放版权的。

 

以下是一个ATOM 的示例

<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom">  <title type="text">dive into mark</title>  <subtitle type="html">    A &lt;em&gt;lot&lt;/em&gt; of effort    went into making this effortless  </subtitle>  <updated>2005-04-02T12:29:29Z</updated>  <id>tag:example.org,2003:3</id>  <link rel="alternate" type="text/html"   hreflang="en" href="http://example.org/"/>  <copyright>Copyright (c) 2003, Mark Pilgrim</copyright>  <generator uri="http://www.example.com/" version="1.0">    Example Toolkit  </generator>  <entry>    <title>Atom draft-07 snapshot</title>    <link rel="alternate" type="text/html"     href="http://example.org/2005/04/02/atom"/>    <link rel="enclosure" type="audio/mpeg" length="1337"     href="http://example.org/audio/ph34r_my_podcast.mp3"/>    <id>tag:example.org,2003:3.2397</id>    <updated>2005-04-02T12:29:29Z</updated>    <published>2003-12-13T08:29:29-04:00</published>    <author>      <name>Mark Pilgrim</name>      <uri>http://example.org/</uri>      <email>f8dy@example.com</email>    </author>    <contributor>      <name>Sam Ruby</name>      <uri>http://intertwingly.net/blog/</uri>    </contributor>    <contributor>      <name>Joe Gregorio</name>      <uri>http://bitworking.org/</uri>    </contributor>    <content type="xhtml" xml:lang="en"     xml:base="http://diveintomark.org/">      <div xmlns="http://www.w3.org/1999/xhtml">        <p><i>[Update: The Atom draft-07 snapshot is out.]</i></p>      </div>    </content>  </entry></feed>

拒绝了对对象 ’sp_sdidebug’(数据库 ‘master’,所有者 ‘dbo’)的 EXECUTE 权限

星期四, 十一月 6th, 2008

在.net中调用时出现“

拒绝了对对象 ’sp_sdidebug’(数据库 ‘master’,所有者 ‘dbo’)的 EXECUTE 权限

的错误的解决办法。

该问题是我在用指定的URL启动项目后,再“附加进程”后运行程序时出现的。该问题主要是.net2005的调试机制引起的,当已启动程序,再附加进程后,他默认是要对SQL Server 也要进行调试的,可这需要装补丁才能支持。所以就出现了“拒绝了对对象 ’sp_sdidebug’(数据库 ‘master’,所有者 ‘dbo’)的 EXECUTE 权限”的错误。这时我们可以通过更改它的调试类型来处理该问题,并使调试正常进行。

在“附加到进程”对话框中点击“附加到:”后的“选择”按钮,可以看到它默认的选项是“自动确定要调试的代码类型”。完后选中“调试以下代码”,并只选择“托管”。这样就可以正常进行了。

另外,若项目整体无法启动调试,也可以先在项目属中指定从某一URL进行调试,完后在启动之后通过上面的方法将该进程附加到调试器中也可以实现对项目的调试。

.net将IP转换为10进制

星期二, 十月 7th, 2008

我们通常在BBS或网上下载的IP地址数据库中的IP地址并非是我们常见的格式(61.175.232.30),而是这种(1034938398)类型的 数据,看起来这两个数据好像没有关连,很复杂,其实并不复杂,以“61.175.232.30”这个IP地址为例,IP地址转换成数字串方法如下:先将 “61.175.232.30”转换为十六进制“3d.af.e8.1e”,然后去掉小数点后,变为“3dafe81e”,最后将这个十六进制数转换为十 进制“1034938398”,那么“61.175.232.30”就变为“1034938398”了。

下面提供用C#实现IP地址转换的代码:

[code=csharp]//IP地址
 string Ip = "61.175.232.30";
 //取出IP地址去掉‘.’后的string数组
 string [] Ip_List = Ip.Split (".".ToCharArray ());
 string X_Ip = "";
 //循环数组,把数据转换成十六进制数,并合并数组(3dafe81e)
 foreach(string ip in Ip_List)
 {
 X_Ip += Convert.ToInt16 (ip).ToString ("x");
 }
//将十六进制数转换成十进制数(1034938398)
 long N_Ip = long.Parse (X_Ip, System.Globalization.NumberStyles.HexNumber);
[/code]

OK,就这样转换成功了,不信,你可以用windows的命令行工具测试一下,ping 61.175.232.30 和 ping 1034938398 的效果是一样的,都是指向 61.175.232.30 的