分類:编程

CSV parser by Regular Expression

Each column in a CSV file is seperated by a comma (,), if the field contains a comma inside, then it has to be bound by a pair of quote (“). Here below is an example:

0566000,1005660003,UG,MEDUU,MEDU_PGF,,MED,MBCHB,F,PGM,MEDUU,F,MBCHB,"M.B., CH.B.",UG

Therefore, we cannot simply parse the file by string.split(new char[] {,}). In this passage, I will use the regular expression instead to separate each column. First, we define the regular expression we use:

(((\"[^\"]*\")|([^\,\"]*))\,{1})|(\"[^\"]*\")|([^\,\"]*)

the source code would be:

string s = sr.ReadLine();
Regex Reg = new Regex(“(((\\\"[^\\\"]*\\\")|([^\\,\\\"]*))\\,{1})|(\\\"[^\\\"]*\\\")|([^\\,\\\"]*)", RegexOptions.IgnoreCase);
MatchCollection match = Reg.Matches(s);
string[] columns = new string[match.Count];
for (int j=0; j < match.Count ; j++)
{
columns[j] = match[j].Value;
}

So, we get the result.

Of course, you will then need to remove the comma or quote if you want. But at least we can parse them without any problem.

从BlogEngine.NET迁移到WordPress

刚刚完成从BlogEngine.NET迁移到WordPress的过程。为什么要迁移?很简单,PHP的成本实在是比ASP.NET划算太多了。外面web hosting的plan,同样配置的话php要比asp的便宜百分之30以上。像我现在用的就只要港币4元一个月,用ASP.NET的话根本做不到。当然,如果你是在家里用旧电脑架的服务器,当然就没什么区别了。话说回来,港币4元绝对比服务器的电费便宜。

迁移很简单,用过BE的人都知道,BE有export的功能,可以将所有文章+评论输出成BlogML格式。遗憾的是,WP本身没有自带Import BlogML格式的工具。于是,我们首先要去下载一个,跟着这个链接就对了:

http://www.kavinda.net/2008/10/23/migrating-from-dasblog-to-wordpress.html

文中本来说的是从DasBlog到Wordpress的迁移。但DasBlog也是输出到BlogML格式的,所以该工具对我们来说也适用。最后,当你Import完之后,只要将Category的名称(会变成一堆数字和字母)改回来就大功告成了。

MS SQL Server – Convert()

Syntax

Using CONVERT:

CONVERT data_type length , expression [ , style )

Arguments

expression

Is any valid Microsoft® SQL Server™ expression. For more information, see Expressions.

data_type

Is the target system-supplied data type, including bigint and sql_variant. User-defined data types cannot be used. For more information about available data types, see Data Types.

length

Is an optional parameter of ncharnvarcharcharvarcharbinary, or varbinary data types.

style

Is the style of date format used to convert datetime or smalldatetime data to character data (ncharnvarcharcharvarcharnchar, or nvarchar data types), or the string format when converting float, realmoney, or smallmoney data to character data (ncharnvarchar, charvarcharnchar, or nvarchar data types).

Without century (yy) With century (yyyy) Standard Input/Output**
0 or 100 (*) Default mon dd yyyy hh:miAM (or PM)
1 101 USA mm/dd/yy
2 102 ANSI yy.mm.dd
3 103 British/French dd/mm/yy
4 104 German dd.mm.yy
5 105 Italian dd-mm-yy
6 106 dd mon yy
7 107 Mon dd, yy
8 108 hh:mm:ss
9 or 109 (*) Default + milliseconds mon dd yyyy hh:mi:ss:mmmAM (or PM)
10 110 USA mm-dd-yy
11 111 JAPAN yy/mm/dd
12 112 ISO yymmdd
13 or 113 (*) Europe default + milliseconds dd mon yyyy hh:mm:ss:mmm(24h)
14 114 hh:mi:ss:mmm(24h)
20 or 120 (*) ODBC canonical yyyy-mm-dd hh:mi:ss(24h)
21 or 121 (*) ODBC canonical (with milliseconds) yyyy-mm-dd hh:mi:ss.mmm(24h)
126(***) ISO8601 yyyy-mm-dd Thh:mm:ss.mmm(no spaces)
130* Hijri**** dd mon yyyy hh:mi:ss:mmmAM
131* Hijri**** dd/mm/yy hh:mi:ss:mmmAM

Example

select CONVERT(varchar, getdate(), 120 )
2004-09-12 11:06:08

select replace(replace(replace(CONVERT(varchar, getdate(), 120 ),’-‘,”),’ ‘,”),’:’,”)
20040912110608

select CONVERT(varchar(12) , getdate(), 111 )
2004/09/12

select CONVERT(varchar(12) , getdate(), 112 )
20040912

select CONVERT(varchar(12) , getdate(), 102 )
2004.09.12

select CONVERT(varchar(12) , getdate(), 101 )
09/12/2004

select CONVERT(varchar(12) , getdate(), 103 )
12/09/2004

select CONVERT(varchar(12) , getdate(), 104 )
12.09.2004

select CONVERT(varchar(12) , getdate(), 105 )
12-09-2004

select CONVERT(varchar(12) , getdate(), 106 )
12 09 2004

select CONVERT(varchar(12) , getdate(), 107 )
09 12, 2004

select CONVERT(varchar(12) , getdate(), 108 )
11:06:08

select CONVERT(varchar(12) , getdate(), 109 )
09 12 2004 1

select CONVERT(varchar(12) , getdate(), 110 )
09-12-2004

select CONVERT(varchar(12) , getdate(), 113 )
12 09 2004 1

select CONVERT(varchar(12) , getdate(), 114 )
11:06:08.177

OpenCV2.0

安装

首先,OpenCV从2.0开始,用了CMake来产生Makefile,所以编译之前要先下载并安装CMake. 之后,下载并安装OpenCV。安装的时候选择Add path to All users。其他用预设值就可以了。安装之后打开CMake,source code输入C:\OpenCV2.0(你的安装路径),build folder随便输入一个你存放的位置。之后按configure,他会让你选你的编译器,用visual studio的话就选你正在用的vs版本吧。最后勾上你要生成的project,按generate就可以了。

编译

去build folder,打开OpenCV.sln就可以用visual studio正常编译了。如果是使用visual c++ express 2008的话,在编译的时候会提示缺少opm.h opmassem.h和vcomp.lib vcompd.lib这几个文件,找台有装visual studio 2008的电脑拷过来放在相应位置就可以了。

使用OpenCV

  • 打开VS2008,Tools->Options
  • Project and Solution -> VC++ Directories
  • 从Show directories中选择library
  • 添加C:\OpenCV2.0\lib
  • 从Show directories中选择include
  • 添加C:\OpenCV2.0\include\opencv

新建项目

  • Create a new C++ project
  • Project -> Properties
  • Configuration Properties -> Linker -> Input
  • 在Additional Dependency 输入以下档案:cxcore200.lib cv200.lib ml200.lib cvaux200.lib highgui200.lib
  • 成功编译

“Program failed to initialize properly 0xc0150002″ error

一般来说编译通过之后就可以执行,但使用Visual C++ express的朋友可能会出现以上错误。只要去下载并安装Microsoft Visual C++ 2008 Redistributable Package (X86)就可以解决这个问题了。

Cloud Computing 2

上文介绍了一些云计算的基本情况。说到云计算,就不得不提google这个将云计算发挥得淋漓尽致的公司。Google的网上办公(google apps)可以说是云计算的代表作,使用了google apps之后,公司不用再自己维护一堆服务器,使得公司的IT人员从繁琐的设定和高昂的维护费用中解放出来。有兴趣的人其实可以自己上网登记体验一下,25个账户以下的服务都是免费的。如果拥有自己的域名的话,更加可以通过设置CNAME来“个人化”自己的服务。比如说,我现在就有以下的服务:

http://mail.jiyunalex.com

http://docs.jiyunalex.com

http://calendar.jiyunalex.com

这三个分别是邮箱,文件和日历服务。所以呢,现在如果你发邮件到admin@jiyunalex.com的话,我就可以从下面这个画面登录进去检阅:

怎么样?cool吧。文件和日历功能都是类似的。当然,这些都是面向企业服务的,普通用户可能不会接触到。其实除了google,也有其他公司提供类似的云计算服务,其中一个就是www.dreamhostapps.com

dreamhostapps可以让用户免费寄存自己的网站,该网站提供了5个常用的服务,分别是WordPress, Drupal, ZenPhoto, phpBB和MediaWiki。用户登记之后就可以选择安装自己需要的服务。同样的,只要你有自己的域名,设定好一个CNAME之后,就相当于自己配置了一个服务器:

http://photo.jiyunalex.com

http://forum.jiunalex.com

通过这些服务,就可以省却自己架设和管理一台服务器的麻烦了。

Multipart form POST in C#

关于Multipart message的格式,可以参考W3C的网站,本文集中演示怎样用C#代码实现该类消息的传送。

[code:c#]

public static class FormUpload
    {
        public static HttpWebResponse MultipartFormDataPost(string postUrl, string userAgent, Dictionary<string, object> postParameters)
        {
            string formDataBoundary = “—————————–28947758029299″;
            string contentType = “multipart/form-data; boundary=" + formDataBoundary;

            byte[] formData = GetMultipartFormData(postParameters, formDataBoundary);

            return PostForm(postUrl, userAgent, contentType, formData);
        }
        private static HttpWebResponse PostForm(string postUrl, string userAgent, string contentType, byte[] formData)
        {
            HttpWebRequest request = WebRequest.Create(postUrl) as HttpWebRequest;

            if (request == null)
            {
                throw new NullReferenceException(“request is not a http request");
            }

            // Set up the request properties

            request.Method = “POST";
            request.ContentType = contentType;
            request.UserAgent = userAgent;
            request.CookieContainer = new CookieContainer();
            request.ContentLength = formData.Length;  // We need to count how many bytes we’re sending.

            using (Stream requestStream = request.GetRequestStream())
            {
                // Push it out there

                requestStream.Write(formData, 0, formData.Length);
                requestStream.Close();
            }

            return request.GetResponse() as HttpWebResponse;
        }

        private static byte[] GetMultipartFormData(Dictionary<string, object> postParameters, string boundary)
        {
            Stream formDataStream = new System.IO.MemoryStream();
            Encoding encoding = Encoding.Default;

            foreach (var param in postParameters)
            {
                if (param.Value is byte[])
                {
                    byte[] fileData = param.Value as byte[];

                    // Add just the first part of this param, since we will write the file data directly to the Stream

                    string header = string.Format(“–{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: application/octet-stream\r\n\r\n", boundary, param.Key, param.Key);
                    formDataStream.Write(encoding.GetBytes(header), 0, header.Length);

                    // Write the file data directly to the Stream, rather than serializing it to a string.

                    formDataStream.Write(fileData, 0, fileData.Length);
                }
                else
                {
                    string postData = string.Format(“–{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", boundary, param.Key, param.Value);
                    formDataStream.Write(encoding.GetBytes(postData), 0, postData.Length);
                }
            }

            // Add the end of the request

            string footer = “\r\n–" + boundary + “–\r\n";
            formDataStream.Write(encoding.GetBytes(footer), 0, footer.Length);

            // Dump the Stream into a byte[]

            formDataStream.Position = 0;
            byte[] formData = new byte[formDataStream.Length];
            formDataStream.Read(formData, 0, formData.Length);
            formDataStream.Close();

            return formData;
        }

    }

[/code]

上面的FormUpload类目的是构造消息,下面就是FormUpload类的调用方法:

[code:c#]

        static void Main(string[] args)
        {
            // Read file data

            FileStream fs = new FileStream(“c:\\example.txt", FileMode.Open, FileAccess.Read);
            byte[] data = new byte[fs.Length];
            fs.Read(data, 0, data.Length);
            fs.Close();

            // Generate post objects

            Dictionary<string, object> postParameters = new Dictionary<string, object>();
            postParameters.Add(“user", “fdreader");
            postParameters.Add(“pass", “pl!mnsj@38“);
            postParameters.Add(“logfile", “example.txt");
            postParameters.Add(“example.txt", data);

            // Create request and receive response

            string postURL = @"http://bigbird.itsc.cuhk.edu.hk/etickettest/palm/attendance.asp“;
            string userAgent = “Someone";
            HttpWebResponse webResponse = FormUpload.MultipartFormDataPost(postURL, userAgent, postParameters);

            // Process response

            StreamReader responseReader = new StreamReader(webResponse.GetResponseStream());
            string fullResponse = responseReader.ReadToEnd();
            webResponse.Close();
            Console.Write(fullResponse);
            Console.ReadKey();
        }

[/code]

Cloud Computing

云计算(Cloud Computing)一词,起源于2004年左右,意指将所有软件和大部分的计算功能都放在一块云里面。客户端只需要安装一个云端程序(PC上一般已浏览器为主),就可以使用大量由云提供的服务。套句老话,这其实是一个瘦客户端-肥服务端模型,这个模型与十几二十年前的模型本质上是一样,但他们的出现原因和运作方法却不太一样。在十几年前,个人电脑刚刚兴起的年代,客户端的运算能力非常有限,而且当时人们对于服务商提供的服务没有什么要求,一般来说只要求文字和图片,对服务器的要求相对来说比较低。所以当年大部分的运算都是在服务端进行的。这就是当年的瘦客户端模型。后来,随着接入互联网的人数逐年提高,并且人们希望能得到更多的多媒体内容,服务器慢慢变得不胜负荷。这个时候由于个人电脑的速度也在不断提升。于是,就有人提出将一部分的运算放到客户端上运行,从而减低服务器的负荷。这就形成了肥客户端模型。可是到了现在,人们对于软件的需求又有了新的变化。随时可得和永不丢失的数据,即时更新的信息都是人们需要的东西。得益于高速发展的互联网,于是又有人提出将所有数据和运算重新归纳到服务端(云)上,客户只需要手持一台能上网的机器(手机,PDA,MID)就能随时随地访问到需要的数据和服务。在这种背景下,云计算就诞生了。

云计算有以下的特点:

  • 所有服务都是基于网络的(Web-based)。客户端只需要安装一个浏览器就可以访问所有服务。
  • 客户端不会储存任何资料和数据。所有东西都保存在服务器(云)上,这样用户无论何时何地在任何一台电脑上,都能访问到属于自己的个人数据。
  • 服务是通用的,就像Microsoft Office等通用软件一样,你可以做一些个性化的设置,但不会专门有大规模的customization。

对于企业用户来说,云计算可以省却维护服务器的麻烦。服务提供商为你提供了必要的软件和硬件维护,并且有24小时专人技术支持。企业能省下大量维护和升级的费用,所以云计算是很受欢迎的。

Web Application Security

今天公司培训,去上了一天课,讲的主题是“Web Application Security”。主讲人是一个老外,handshake networking的consultant。我觉得讲的内容很不错,在这里和大家分享一下吧。

Web Application Security

 

随着网络高速发展,越来越多公司将部分业务放在网上。一来方便了客户,二来也减低了公司本身的行政费用。以前黑客们大多将精力集中在OS或者Web Server层面。比如说Windows的漏洞或者是IIS,Apache的漏洞,并加以攻击。但随着这些软件的不断完善,攻击的难度也越来越大。相比起来,Web Application层面的攻击就比较容易。原因有几个:第一,OS和Web Server的漏洞可以通过patch的形式修复,一旦开发商发布这些patch,大部分电脑的漏洞都可以堵塞。但Web Application都是自己开发的,这个堵塞了漏洞,另一个还可以用同样的手法攻击。第二,Web Application的开发都是小规模进行,质量良莠不齐,攻击起来相对简单。

程序员避免犯的错误

 

在这里说几个常犯的错误吧。

  1. 不要在同一个目录下备份文件。一般来说,程序员有个习惯就是做任何修改之前先备份一下,将原来的文件改成.bak, .tmp之类的。如果黑客知道我们的文件名(不可能不知道,就在网址里),就可以尝试下载有这些后缀的文件,找到的话,我们的源代码就会被直接下载咯。
  2. 修改Web Server的默认设置。修改Web Server的设置,使得返回的http header不会有IIS/6.0或Apache 2.2.1之类可以告诉黑客服务器版本的东西。因为这信息有助于黑客锁定攻击你的方法。而且主讲人还说了一个很重要的原因。大部分黑客都是没有既定目标的,他们只是在网上漫游,寻找合适的网站来攻击。如果你的网站返回的是没有任何意义的东西,他们就会觉得那管理员最起码懂一点安全的东西。于是就会放弃这个网站,直接寻找下一个。哈哈,这个强吧。
  3. 尽量不要将多个Application放在同一个服务器中。因为你永远不知道别人的Application有什么漏洞,所以每增加一个Application就等于增加了该服务器被攻击的机率。要知道,一个Application被攻破,黑客就可以通过其他方法拿到别的Application的控制权。

目前先说这么多吧。

Slide Show widget for BlogEngine.NET

今天用jquery写了一个给BlogEngine.NET用的slide show小工具。最重要的功能是你可以通过edit来自己上传照片,并且照片在上传后会在服务器背后自动压缩,以减低容量要求。啥也不说了,看首页右面的例子就是了,呵呵。

马上下载来玩玩吧。

This widget is written in jquery, an open source javascript library. It allows you to upload your own photos and display it as a slide show. You can see the effect on the Homepage. Please download it right below, a readme file is included.

SlideShow