RSS 2.0 Feed

Saturday, July 12, 2008

       一般来说,我们把报表分为两类,一类是ad-hoc的报表,用于实时查询,客户可以输入特定的参数,得到他们感兴趣的报表,还有一类是scheduling的报表,用于自动生成,一般包括daliy,monthly,quarterly和yearly的报表,这种定制类的报表,可以在指定的时间,生成到指定的目录,他们生成的内容也会提前定制,参数不可更改。一般在报表的需求定义中,客户都会要求报表能够做到自动生成,这也就是我们所说的第二类报表,有时候,客户还会要求能够在自动生成的同时,实现自动打印。下面我们来谈谈如何实现报表的自动生成以及自动打印。

       首先来谈谈解决方案,由于RS提供web service式的调用,因此我们可以写一个remoting service或者windows service或者仅仅是一段程序,然后由job之类的调用,来实现报表的自动。在程序中,我们调用RS,来实现报表的生成。需要生成的报表列表,报表的参数(时间参数),导出文件的格式,我们定义在数据库里,解决方案简单的用图表来表现如下:

image

下面我们来谈具体的步骤

第一步:创建项目,添加web引用(C#项目),URL为http://localhost/ReportServer/ReportService.asmx

clip_image004

第二步,取参数以及定义其他的参数。

参数表的内容为:

ReportName PeriodType PromptName1 Prompttype1 Format

SupplierD D date datetime PDF

SupplierM M date datetime PDF

SupplierQ Q date datetime PDF

SupplierY Y date datetime PDF

ReportName为报表的名称,PeriodType为报表的类别,分别是日报,月报,季度报和年报,PromptName1和Prompttype1为参数的名字和类别,如果有需要,可以加更多的参数。Format为报表导出的格式。(为方便描述,下述代码中的参数都写死,实际操作中,会从数据库或者从注册表中读取。)

定义参数的代码为:

ParameterValue[] parameters = null;

parameters[1] = new ParameterValue();

parameters[1].Name = “date”;

parameters[1].Value =”01/01/2008”;

 

定义其他参数:

string devInfo = @"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";

string encoding;

string mimeType;

Warning[] warnings = null;

string[] streamIDs = null;

DataSourceCredentials[] credentials = null;

ParameterValue[] used = null;

 

第三步,生成报表并得到报表的二进制流

ReportingService rep = new ReportingService();

rep.Credentials = rep.Credentials = System.Net.CredentialCache.DefaultCredentials;

byte[] ss = null;

得到报表:

ss = rep.Render(“SupplierD” , “PDF”, null, devInfo, parameters, credentials, null, out encoding, out mimeType, out used, out warnings, out streamIDs);

使用的方法是RS提供的

Render ( Report As string ,  Format As string ,  HistoryID As string ,  DeviceInfo As string ,  Parameters As ArrayOfParameterValue ,  Credentials As ArrayOfDataSourceCredentials ,  ShowHideToggle As string ) As base64Binary

 

第四步:将生成的报表保存到服务器

FileStream repFile = new FileStream(@“D:\Report\ SupplierD”, FileMode.Create);

repFile.Write(ss, 0, ss.Length);

repFile.Close();

 

第五步:自动打印生成的报表

System.Diagnostics.ProcessStartInfo startInfo = new ProcessStartInfo();

startInfo.Arguments = "/p /h " + @“D:\Report\ SupplierD”;

startInfo.FileName = @"C:\Program Files\Adobe\Reader 8.0\Reader\AcroRd32.exe"; ; //Replace this with the path of the Acrobat Reader executable file, i.e. AcroRd32.exe

startInfo.UseShellExecute = true;

System.Diagnostics.Process process = Process.Start(startInfo);

process.WaitForExit(10000);

if (process.HasExited == false)

{

process.Kill();

}

       这里的方法其实是打印已经生成的PDF文件,所以要求该机器必须装有Acrobat Reader。不选用直接打印二进制数据流,是因为这种打印方法无法设置横向打印(Landscape)或者是竖向打印(Portrait),而报表肯定是有横向有竖向的。不选用打印生成html文件的方式,是因为RS不支持导出HTML,只支持MHTML,而MHTML转成HTML太麻烦。

       最后,有几点需要注意的是,RS导出的报表必须是已经发布到Report server上的,调用render方法时,第一个参数Report As string必须和reportserver上的路径一致,比如报表的发布路径是Report/SupplierD,那么这个参数的值为”Report/SupplierD”。还有一个要注意的是如果制作报表时,参数设置成下拉框式(如下图),那么传入的值必须是这些值其中之一或者之几(看是否是Multi-value)。

clip_image006

留言请访问如下链接:

Reporting Service Tips 101(#4) - 使用RS实现报表的自动生成以及在程序中调用RS

posted @ | Feedback (2) | Filed Under [ Reporting Service Tips 101 ]

接上一篇(Reporting Service Tips 101 - 关于使用Sum函数会遇到的问题(1)),谈谈使用sum可能会遇到的另外一个问题。

Dateset的数据如下:

Supplier      Revenue    status

A               5.00        0

A               6.00        1

A               7.00        0

需求是只用sum算出Supplier A在status为0时候的Revenue总和。单看这个需求,我们其实很容易用在报表中添加分组,或者直接在数据的上一层group来解决,但是在做很多复杂报表的时候,如果能够在计算公式里面去解决一些问题,整个报表的开发过程会简单得多。

报表如下:

clip_image001

计算公式为:=FormatNumber(Sum(Fields!Revenue.Value and Fields!status.Value=0),2)

结果如下:

clip_image002

可以看到,正是我们想要的结果。但是这种方法,在遇到很复杂的报表的时候,有时候会有问题,所以我们还可以用另外一种方法。

报表:

clip_image003

计算公式为:=FormatNumber(Sum(iif(Fields!status.Value=0,Fields!Revenue.Value,0)),2)

结果:

clip_image004

和上一种方法的结果一样,但是这种方法的好处是,基本上无论多复杂的报表,都不会有问题。

留言请访问如下链接:

Reporting Service Tips 101(#3) - 关于使用Sum函数会遇到的问题(2)

posted @ | Feedback (1) | Filed Under [ Reporting Service Tips 101 ]

Thursday, July 10, 2008

用过Reporting service (后面都用RS代替)的人对sum这个函数都不会陌生,这个函数的使用率极高并且非常好用,下面我们就来谈谈使用这个函数可能会遇到的一个问题。

我们先假设报表使用的dataset传过来的数据如下

Supplier      Revenue

A                   0.00

B                   0.00

报表的需求是要算出每个Supplier的Revenue所占的比率。我们在报表中新建一个table,table中新建一个group,group绑定的值为Fields!SupplierName.Value,group的名字为SupplierGroup,该Dataset的名字为Dssup。报表如下:

clip_image002

可以看到比率的计算公式为:

=FormatPercent(Sum(Fields!Revenue.Value,"SupplierGroup")/Sum(Fields!Revenue.Value,"Dssup"),2)

但事实上,由这个计算公式得到的值却是这样:

clip_image004

这个很好理解,是因为我们的计算公式的分母为0,所以出现了NaN这种值,这个时候,按照正常的逻辑,我们都会选择先判断一下分母,改后的计算公式是这样(为了便于查看,先去掉函数FormatPercent):

iif(Sum(Fields!Revenue.Value,"Dssup") = 0, 0.00%, Sum(Fields!Revenue.Value,"SupplierGroup")/Sum(Fields!Revenue.Value,"Dssup"))

 

这个是说如果分母为0,那么传回0.00%,反之通过公式计算。从这个公式来看,没有问题,但是不幸的是,结果依然是NaN。

那么怎么办呢,继续尝试下去,改计算公式为

iif(Sum(Fields!Revenue.Value,"SupplierGroup")/Sum(Fields!Revenue.Value,"Dssup")=’NaN’, 0.00%, Sum(Fields!Revenue.Value,"SupplierGroup")/Sum(Fields!Revenue.Value,"Dssup"))

 

结果证明,改成这样,还是不行。

这个时候,考虑到当Sum(Fields!Revenue.Value,"Dssup") = 0 时,Sum(Fields!Revenue.Value,"SupplierGroup")一定也为0,所以改计算公式为:

Sum(Fields!Revenue.Value,"SupplierGroup")/iif(Sum(Fields!Revenue.Value,"Dssup")=0,1,Sum(Fields!Revenue.Value,"Dssup"))

既如果分母为0,那么强制将分母变为1,最后结果为

clip_image006

这是我们想要的结果。最终计算公式是:

=FormatPercent(Sum(Fields!Revenue.Value,"SupplierGroup")/iif(Sum(Fields!Revenue.Value,"Dssup")=0,1,Sum(Fields!Revenue.Value,"Dssup")),2)

留言请访问如下链接: Reporting Service Tips 101(#2) - 关于使用Sum函数会遇到的问题(1)

posted @ | Feedback (0) | Filed Under [ 程序人生 ]

Monday, July 07, 2008

Reporting Service有三种报表发布方式:

一、是在报表管理器上直接上传报表,创建数据源,这种方式很麻烦,只适用于少量的报表。

二、是在VS.net里的project里面直接发布,这种只适用于开发环境。

三、就是使用RSS脚本进行自动发布。下面我们就来初步了解一下RSS这种发布方式。


默认情况下,安装完Reporting Service,我们可以在Microsoft SQL Server\90\Samples\Reporting Services\Script Samples目录下找到一个名为PublishSampleReports.rss的文件,同时在联机文件中,我们也可以找到该文件。这个RSS文件就是自动发布的脚本,但是内容比较基础简单,下面我们在这个文件基础上进行一些扩展。


1.    这个是一个比较重要的问题,提供的RSS脚本,要求默认windows认证或者允许匿名访问,但是在实际的生产环境中,一般是用的域认证,且出于安全考虑,禁止匿名访问。所以这一块,我们要改变RSS的认证方式。
       已有的代码是:
rs.Credentials = System.Net.CredentialCache.DefaultCredentials
       改为:
rs.Credentials = new System.Net.NetworkCredential(User_Name,User_Password,User_domin)
       然后在命令行里面加上这三个参数即可:
rs -i PublishSampleReports.rss -s http://ReportServerName/reportserver -u UserName -p UserPassword\Userdomin


       在指定的服务器上进行发布时,有关权限问题这一块,我们还应当考虑是否拥有报表服务器的访问权限,以及是否对对要访问的报表服务器的根文件夹具有相应的权限。在实际操作中,权限问题是报得最多的error。


2.该脚本必须用Visual Studio VB.NET语言编写,因此也可以用VB.NET进行一些额外的操作,例如判断报表是否已经被发布。

留言请访问:Reporting Service Tips 101(#1) - 使用RSS在指定的服务器上自动进行ReportingService报表发布

posted @ | Feedback (0) | Filed Under [ 程序人生 ]

Sunday, June 22, 2008

先从SQL注入攻击说起吧。

前一段时间的SQL注入攻击可以说让国内以及国外大量网站沦陷,几个攻击变种中幸好是update而不是delete,否则众多网站损失更大,不过从犯罪的角度来说,并不是这些攻击者心慈手软,而是update才能置入网页木马,也才能在置入成功后获得预期的利润。此次大规模的SQL Injection是使用一个叫做Asprox的自动化工具来借助Google搜索引擎寻找目标网站并自动实施SQL注入的,就连趋势科技网站也未能幸免,惨被注入。此次SQL注入攻击风潮从3月份开始,进入6月份后被攻击的网站仍在大量沦陷。

在很多所谓的开发高手来看,SQL注入只是菜鸟才会犯的低级错误,其实不然。一个中大型的网站,在他不断发展的过程中,网站门户的程序都是Patch模式的逐步叠加,随着页面的增加以及版本的螺旋上升,SQL注入的危险百分比也会指数增长,尤其是国内各个网站开发的模式而言。当一个中大型网站的页面达到几万甚至几十万的时候,当这个网站的程序不断叠加积累,诸多历史页面已经处于失控的时候,如何避免SQL Inject攻击将会是一件令人非常头疼的事情,因为你此时是不可能完全重写整个网站或者完全对所有页面做代码安全审核的。

在这众多的历史页面代码中,一个微小的疏漏就导致你的DB完全向攻击者敞开,甚至威胁到服务器磁盘数据。不要侥幸的认为,你的漏洞页面有可能隐藏的很深,现在对于Google而言,什么都不是隐藏的,再加上SQL注入的自动化操作,你的历史页面越多,你的危险就越大。

我以SQL Injection为例就是为了说明其实Web威胁攻击并不是说需要多么高深的技术才可以进行实施,这些攻击往往是你在认为很简单就可以抵御的时候来进行实施的。另外一个极端就是,所谓的社会工程学攻击,各位可以Google一下就会了解。可以说 ,目前的各类攻击已经不再像很早以前那样为了显示自身技术而进行的有意或无意的攻击破坏了,现在大量的Web攻击都是带有利益驱使性的,也更具危害性。

这些Web攻击都是非常危险的,因为不论你的硬件防火墙或者入侵检测系统如何强大,是无法判断这类Web攻击的,因为它们都是合法的HTTP请求。所以根据统计,目前的Web攻击除了操作系统以及各类服务器端应用软件的漏洞外,绝大部分(70%以上)都是此类“合法的”Web攻击。

因此,抵御此类攻击一是需要检测你的应用程序代码,二是可以采用服务器端的针对访问请求以及内容的检测过滤。

针对第一类,目前业界有非常多的安全检测工具,比如HP WebInspect,NStalker-WAS(NStalker-Web Application Security Scanner),IBM Rational AppScan(Watchfire AppScan),Acunetix Web Vulnerability Scanner等等,当然这里我列举的都是商业软件,而没有包含相应的开源软件,在这方面而言,商业软件用来做安全威胁评估的优势更明显,也更合适。

这类模拟攻击检测软件有庞大的规则库以及模拟场景库,可以代替繁杂易错的人工检测。

针对第二类,则可以通过服务器端的过滤和监测机制来最大程度上保证IIS Web服务器的安全,比如微软的IIS Lock。在IIS 7推出后,做此类过滤更加简单和便捷了。国内外也有针对此类的软件产品,比如Port80 ServerDefender。这类产品可以在服务器端对于HTTP Request / POST / Cookie等做过滤和检测,抵御此类Web攻击。

image

(此图片转自于IBM网站,特注明)

 

排名前两位的是XSS攻击以及SQL Injection攻击。对于XSS攻击,很多开发者想必会嗤之以鼻的,因为目前而言XSS攻击都很少能破坏掉服务器端的数据,但是XSS最大危害在于钓鱼式攻击,这对于一个成功的网站而言,对其信誉的打击将是致命的,因为展现在用户面前的是合法的网站URL地址,只是XSS攻击部分被编码了。一旦用户遭受此类攻击,对于你网站的信任将会大大降低,现在有什么比得罪你的忠实用户的危害性更大呢?

上面我们提到了很多安全检测工具,其中提到的那四种工具我都有过一定使用(Trial或者Test),其中的AppScan是我印象最为深刻的,也是效果较好的一个。Rational家族随着IBM的不断收购,已经越来越庞大,通过收购Watchfire从而获得了这款企业级安全检测产品,并被Rational产品系列所整合,使之符合Rational的完整涵盖软件生命周期的目的。

image

Rational AppScan开发版本会有针对于Visual Studio 的AddIn,来在程序开发过程中就能进行代码安全审计和检测;同时也有QA版本;当然我们使用更多的是产品发布后定期的安全审计以及检测了。各版本的比较可以参见:http://www-142.ibm.com/software/dre/hmc/compare.wss?HMC02=C126096V43460Q17 

Rational AppScan 7.7全功能测试版本在IBM网站可以免费下载到(http://www14.software.ibm.com/webapp/download/search.jsp?pn=Rational+AppScan),目前CSDN好像也在进行AppScan的市场活动,有兴趣可以去CSDN找一下即可。

下一个post会详细讲述一下如何针对一个真实网站进行安全审计。

 

---

可能的大概目录

Web攻击和防御(一) - 安全检测工具(1)介绍

Web攻击和防御(二) - 安全检测工具(2)AppScan详解

Web攻击和防御(三) - 安全检测工具(3)AppScan数据分析

Web攻击和防御(四) - IIS安全防护,IIS Filter介绍

Web攻击和防御(五) - IIS安全防护,IIS Extend介绍

Web攻击和防御(六) - IIS安全防护,IIS 5.x 、6、7区别对待 

Web攻击和防御(七) - Web Server Guard介绍

Web攻击和防御(八) - Web Server Guard安全防护使用详解

Web攻击和防御(九) - Web Server Guard性能调优使用详解

Web攻击和防御(十) - Web Server Guard服务器监测使用详解

Web攻击和防御(十一) - 完成不可能的事情:使用C#编写IIS Filter(IIS 5.x/6.0)

Web攻击和防御(十二) - IIS 7.0 Filter

Web攻击和防御(十三) - IIS 7.0 安全防护

Web攻击和防御(..... ) - ..........

posted @ | Feedback (2) | Filed Under [ 程序人生 ]

Thursday, June 19, 2008

UMD格式是国内手机阅读中使用较多的一种格式,但其公司却并没有将UMD数据格式公开,但是却用另外一种方式将其公开,你去访问一下他们的站点然后下载他的制作工具就知道。

下面的是文本的UMD相关处理代码,图形的下一篇post出来。

 

namespace Ikari
{
    using ICSharpCode.SharpZipLib.Zip.Compression;
    using System;
    using System.Collections;
    using System.IO;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Windows.Forms;

    public class UMD_GENEGINE
    {
        private const int A_32K_BYTE = 0x8000;
        private byte ACTUAL_WIDTH_S60_HORI = 0xcc;
        private byte ACTUAL_WIDTH_S60_VERT = 0xac;
        private byte ACTUAL_WIDTH_SP = 0xa6;
        private const uint BASE_REFN_CHAP_OFF = 0x3000;
        private const uint BASE_REFN_CHAP_STR = 0x4000;
        private const uint BASE_REFN_CONTENT = 0x2000;
        private const uint BASE_REFN_COVER = 0x1000;
        private const uint BASE_REFN_PAGE_OFFSET = 0x7000;
        private const string BEYOND_END_FLAG = "\0";
        private const int BYTE_LEN = 1;
        private const byte COVER_TYPE_BMP = 0;
        private const byte COVER_TYPE_GIF = 2;
        private const byte COVER_TYPE_JPG = 1;
        private const int CURR_VERSION = 1;
        private const short DCTS_CMD_ID_AUTHOR = 3;
        private const short DCTS_CMD_ID_CDS_KEY = 240;
        private const short DCTS_CMD_ID_CHAP_OFF = 0x83;
        private const short DCTS_CMD_ID_CHAP_STR = 0x84;
        private const short DCTS_CMD_ID_CONTENT_ID = 10;
        private const short DCTS_CMD_ID_COVER_PAGE = 130;
        private const short DCTS_CMD_ID_DAY = 6;
        private const short DCTS_CMD_ID_FILE_LENGTH = 11;
        private const short DCTS_CMD_ID_FIXED_LEN = 12;
        private const short DCTS_CMD_ID_GENDER = 7;
        private const short DCTS_CMD_ID_LICENSE_KEY = 0xf1;
        private const short DCTS_CMD_ID_MONTH = 5;
        private const short DCTS_CMD_ID_PAGE_OFFSET = 0x87;
        private const short DCTS_CMD_ID_PUBLISHER = 8;
        private const short DCTS_CMD_ID_REF_CONTENT = 0x81;
        private const short DCTS_CMD_ID_TITLE = 2;
        private const short DCTS_CMD_ID_VENDOR = 9;
        private const short DCTS_CMD_ID_VERSION = 1;
        private const short DCTS_CMD_ID_YEAR = 4;
        private const byte FIXED_LINE_PER_PAGE_S60 = 50;
        private const byte FIXED_LINE_PER_PAGE_SP = 0x19;
        private string iAuthor;
        private byte[] ibContent;
        private int[] iChapOff;
        private ArrayList iChapStr = new ArrayList();
        private ArrayList iChapter = new ArrayList();
        private int iCID;
        private string iContent;
        private string iCoverFile;
        private string iDay;
        private string iGender;
        private string iMonth;
        private const int INT_LEN = 4;
        private short iPGKSeed = 0;
        private string iPublisher;
        private string iSaveTo;
        private string iTitle;
        private int iTotalen;
        private string iVendor;
        private ArrayList iWidthData_S60 = new ArrayList();
        private ArrayList iWidthData_SP = new ArrayList();
        private string iYear;
        private byte[][] iZippedSeg;
        private const string KEY_CODE_TAB = "\t";
        private const byte S60_FONT_SIZE_BIG = 0x10;
        private const byte S60_FONT_SIZE_SMALL = 12;
        private const byte SEREIS60_FONTS_COUNT = 2;
        private const int SHORT_LEN = 2;
        private const byte SP_FONT_SIZE_10 = 10;
        private const byte SP_FONT_SIZE_MAX = 0x10;
        private const byte SP_FONT_SIZE_MIN = 6;
        private const string SYMBIAN_RETURN = "\u2029";
        private const string SYMBIAN_SPACE = " ";
        private const byte UMD_DCTD_HEAD_LEN = 9;
        private const byte UMD_DCTS_HEAD_LEN = 5;
        private const int UMD_FREE_CID_MIN = 0x5f5e100;
        private const int UMD_FREE_PGK_SEED_MIN = 0x400;
        private const int UMD_LICENSEKEY_LEN = 0x10;
        private const int UMD_MAX_BOOKMARK_STR_LEN = 40;
        private const byte UMD_PLATFORM_ID_NONE = 0;
        private const byte UMD_PLATFORM_ID_S60 = 1;
        private const byte UMD_PLATFORM_ID_SP = 5;
        private const int UMD_SEGMENT_LENGTH = 0x8000;
        private const byte VER_PKG_LEN = 3;
        private const string WINDOWS_RETURN = "\r\n";
        private const int ZIP_LEVEL = 9;

        private byte CharWidth_S60(string Char, byte pFontSize)
        {
            ushort num = Char[0];
            for (int i = 0; i < this.iWidthData_S60.Count; i++)
            {
                SWidthData data = (SWidthData) this.iWidthData_S60[i];
                if (((data.FontSize == pFontSize) && (num >= data.rngFrom)) && (num <= data.rngTo))
                {
                    if (data.vCount == 1)
                    {
                        return data.Value[0];
                    }
                    return data.Value[num - data.rngFrom];
                }
            }
            return pFontSize;
        }

        private byte CharWidth_SP(string Char, byte pFontSize)
        {
            ushort num = Char[0];
            for (int i = 0; i < this.iWidthData_SP.Count; i++)
            {
                SWidthData data = (SWidthData) this.iWidthData_SP[i];
                if (((data.FontSize == pFontSize) && (num >= data.rngFrom)) && (num <= data.rngTo))
                {
                    if (data.vCount == 1)
                    {
                        return data.Value[0];
                    }
                    return data.Value[num - data.rngFrom];
                }
            }
            return pFontSize;
        }

        private bool GetPageOffsetS60(byte size, uint actual_width, ref ProgressBar pbar, out uint[] result)
        {
            ArrayList pPageoff = new ArrayList();
            if ((size != 0x10) && (size != 12))
            {
                result = new uint[0];
                return false;
            }
            this.GetWidthData_S60();
            pPageoff.Add(0);
            int num = pbar.Value;
            while (((int) pPageoff[pPageoff.Count - 1]) < this.iContent.Length)
            {
                this.ParseOnePage((uint) (pPageoff.Count - 1), size, actual_width, ref pPageoff, 1);
                pbar.Value = num + ((int) ((uint) pPageoff[pPageoff.Count - 1]));
            }
            result = new uint[pPageoff.Count];
            for (int i = 0; i < pPageoff.Count; i++)
            {
                result[i] = ((uint) pPageoff[i]) * 2;
            }
            return true;
        }

        private bool GetPageOffsetSP(byte size, uint actual_width, ref ProgressBar pbar, out uint[] result)
        {
            ArrayList pPageoff = new ArrayList();
            if ((size < 6) || (size > 0x10))
            {
                result = new uint[0];
                return false;
            }
            this.GetWidthData_SP();
            pPageoff.Add(0);
            int num = pbar.Value;
            while (((uint) pPageoff[pPageoff.Count - 1]) < this.iContent.Length)
            {
                this.ParseOnePage((uint) (pPageoff.Count - 1), size, actual_width, ref pPageoff, 5);
                if ((num + ((int) ((uint) pPageoff[pPageoff.Count - 1]))) < pbar.Maximum)
                {
                    pbar.Value = num + ((int) ((uint) pPageoff[pPageoff.Count - 1]));
                }
            }
            result = new uint[pPageoff.Count];
            for (int i = 0; i < pPageoff.Count; i++)
            {
                result[i] = (uint) pPageoff[i];
            }
            return true;
        }

        private void GetWidthData_S60()
        {
            this.iWidthData_S60.Clear();
            for (int i = 0; i < 2; i++)
            {
                string path = "";
                switch (i)
                {
                    case 0:
                        path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase.Remove(0, 8)) + @"\FontWidthData\S60CHS.S16.wdt";
                        break;

                    case 1:
                        path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase.Remove(0, 8)) + @"\FontWidthData\S60CHS.S12.wdt";
                        break;
                }
                if (File.Exists(path))
                {
                    FileStream input = new FileStream(path, FileMode.Open, FileAccess.Read);
                    BinaryReader reader = new BinaryReader(input);
                    while (reader.BaseStream.Position < reader.BaseStream.Length)
                    {
                        ushort num2 = reader.ReadUInt16();
                        ushort num3 = reader.ReadUInt16();
                        uint num4 = reader.ReadUInt16();
                        byte[] buffer = new byte[num4];
                        for (uint j = 0; j < num4; j++)
                        {
                            buffer[j] = reader.ReadByte();
                        }
                        SWidthData data = new SWidthData();
                        switch (i)
                        {
                            case 0:
                                data.FontSize = 0x10;
                                break;

                            case 1:
                                data.FontSize = 12;
                                break;
                        }
                        data.rngFrom = num2;
                        data.rngTo = num3;
                        data.vCount = num4;
                        data.Value = buffer;
                        this.iWidthData_S60.Add(data);
                    }
                    reader.Close();
                    input.Close();
                }
            }
        }

        private void GetWidthData_SP()
        {
            this.iWidthData_SP.Clear();
            for (int i = 0x10; i < 0x11; i++)
            {
                string path = (Assembly.GetExecutingAssembly().CodeBase.Remove(0, 8) + @"\FontWidthData\sunfon.s") + i.ToString() + ".wdt";
                if (File.Exists(path))
                {
                    FileStream input = new FileStream(path, FileMode.Open, FileAccess.Read);
                    BinaryReader reader = new BinaryReader(input);
                    while (reader.BaseStream.Position < reader.BaseStream.Length)
                    {
                        ushort num2 = reader.ReadUInt16();
                        ushort num3 = reader.ReadUInt16();
                        uint num4 = reader.ReadUInt16();
                        byte[] buffer = new byte[num4];
                        for (uint j = 0; j < num4; j++)
                        {
                            buffer[j] = reader.ReadByte();
                        }
                        SWidthData data = new SWidthData();
                        data.FontSize = (byte) i;
                        data.rngFrom = num2;
                        data.rngTo = num3;
                        data.vCount = num4;
                        data.Value = buffer;
                        this.iWidthData_SP.Add(data);
                    }
                    reader.Close();
                    input.Close();
                }
            }
        }

        public bool Initialize(string aTitle, string aAuthor, string aYear, string aMonth, string aDay, string aGender, string aPublisher, string aVendor, string aCoverFile, int aContentID, string aSaveTo, ref ArrayList aChapter, ref ArrayList aChapStr, out string aResult)
        {
            aResult = "true";
            if (aTitle.Length <= 0)
            {
                aResult = "标题不能为空";
                return false;
            }
            if (aAuthor.Length <= 0)
            {
                aResult = "作者不能为空";
                return false;
            }
            if (((aYear.Length > 4) || (aMonth.Length > 2)) || (aDay.Length > 2))
            {
                aResult = "日期非法";
                return false;
            }
            if (aChapter.Count <= 0)
            {
                aResult = "内容数量不能小于0";
                return false;
            }
            if (aChapter.Count != aChapStr.Count)
            {
                aResult = "章节标题数量和章节内容数量不符";
                return false;
            }
            if (!Directory.Exists(aSaveTo))
            {
                aResult = "保存文件的路径不存在";
                return false;
            }
            this.iTitle = aTitle;
            this.iAuthor = aAuthor;
            this.iYear = aYear;
            this.iMonth = aMonth;
            this.iDay = aDay;
            this.iGender = aGender;
            this.iPublisher = aPublisher;
            this.iVendor = aVendor;
            this.iCID = aContentID;
            this.iCoverFile = aCoverFile;
            this.iSaveTo = aSaveTo;
            File.Copy(this.iCoverFile + ".tmp", this.iSaveTo + @"\" + this.iTitle + ".jpg");
            for (int i = 0; i < aChapter.Count; i++)
            {
                this.iChapter.Add(((string) aChapter[i]) + "\u2029");
                this.iChapStr.Add((string) aChapStr[i]);
            }
            this.iChapOff = new int[this.iChapter.Count];
            return true;
        }

        public bool Make(ref ProgressBar pbar, out string result)
        {
            uint[] numArray2;
            this.Prepare();
            Random random = new Random();
            uint num = 0;
            if (this.iSaveTo.EndsWith(@"\"))
            {
                this.iSaveTo.Remove(this.iSaveTo.Length - 1, 1);
            }
            string path = this.iSaveTo + @"\" + this.iTitle + ".umd";
            if (File.Exists(path))
            {
                if (MessageBox.Show("您要保存的文件已经存在,是否覆盖?", "mBook制作工具 版本:1.0", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes)
                {
                    result = "生成文件操作被用户取消";
                    return false;
                }
                File.Delete(path);
            }
            FileStream output = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
            BinaryWriter writer = new BinaryWriter(output);
            byte num1 = Encoding.Unicode.GetBytes((string) this.iChapter[0])[0];
            writer.Write((uint) 0xde9a9b89);
            writer.Write('#');
            writer.Write((short) 1);
            writer.Write((byte) 0);
            writer.Write((byte) 8);
            writer.Write((byte) 1);
            writer.Write(this.iPGKSeed);
            writer.Write('#');
            writer.Write((short) 2);
            writer.Write((byte) 0);
            writer.Write((byte) (5 + (this.iTitle.Length * 2)));
            writer.Write(Encoding.Unicode.GetBytes(this.iTitle));
            writer.Write('#');
            writer.Write((short) 3);
            writer.Write((byte) 0);
            writer.Write((byte) (5 + (this.iAuthor.Length * 2)));
            writer.Write(Encoding.Unicode.GetBytes(this.iAuthor));
            if (this.iYear.Length > 0)
            {
                writer.Write('#');
                writer.Write((short) 4);
                writer.Write((byte) 0);
                writer.Write((byte) (5 + (this.iYear.Length * 2)));
                writer.Write(Encoding.Unicode.GetBytes(this.iYear));
            }
            if (this.iMonth.Length > 0)
            {
                writer.Write('#');
                writer.Write((short) 5);
                writer.Write((byte) 0);
                writer.Write((byte) (5 + (this.iMonth.Length * 2)));
                writer.Write(Encoding.Unicode.GetBytes(this.iMonth));
            }
            if (this.iDay.Length > 0)
            {
                writer.Write('#');
                writer.Write((short) 6);
                writer.Write((byte) 0);
                writer.Write((byte) (5 + (this.iDay.Length * 2)));
                writer.Write(Encoding.Unicode.GetBytes(this.iDay));
            }
            if (this.iGender.Length > 0)
            {
                writer.Write('#');
                writer.Write((short) 7);
                writer.Write((byte) 0);
                writer.Write((byte) (5 + (this.iGender.Length * 2)));
                writer.Write(Encoding.Unicode.GetBytes(this.iGender));
            }
            if (this.iPublisher.Length > 0)
            {
                writer.Write('#');
                writer.Write((short) 8);
                writer.Write((byte) 0);
                writer.Write((byte) (5 + (this.iPublisher.Length * 2)));
                writer.Write(Encoding.Unicode.GetBytes(this.iPublisher));
            }
            if (this.iVendor.Length > 0)
            {
                writer.Write('#');
                writer.Write((short) 9);
                writer.Write((byte) 0);
                writer.Write((byte) (5 + (this.iVendor.Length * 2)));
                writer.Write(Encoding.Unicode.GetBytes(this.iVendor));
            }
            writer.Write('#');
            writer.Write((short) 11);
            writer.Write((byte) 0);
            writer.Write((byte) 9);
            writer.Write(this.ibContent.Length);
            num = (uint) (0x3000L + random.Next(0xfff));
            writer.Write('#');
            writer.Write((short) 0x83);
            writer.Write((byte) 1);
            writer.Write((byte) 9);
            writer.Write(num);
            writer.Write('$');
            writer.Write(num);
            writer.Write((uint) (9 + (this.iChapOff.Length * 4)));
            foreach (int num2 in this.iChapOff)
            {
                writer.Write(num2);
            }
            num = (uint) (0x4000L + random.Next(0xfff));
            writer.Write('#');
            writer.Write((short) 0x84);
            writer.Write((byte) 1);
            writer.Write((byte) 9);
            writer.Write(num);
            int num3 = 0;
            foreach (object obj2 in this.iChapStr)
            {
                num3 += (((string) obj2).Length * 2) + 1;
            }
            writer.Write('$');
            writer.Write(num);
            writer.Write((uint) (9 + num3));
            foreach (object obj3 in this.iChapStr)
            {
                writer.Write((byte) (((string) obj3).Length * 2));
                writer.Write(Encoding.Unicode.GetBytes((string) obj3));
            }
            int num4 = 0;
            int num5 = 0;
            uint[] numArray = new uint[this.iZippedSeg.Length];
            if (this.iZippedSeg.Length > 1)
            {
                num4 = random.Next(0, this.iZippedSeg.Length - 1);
                num5 = random.Next(0, this.iZippedSeg.Length - 1);
            }
            for (int i = 0; i < this.iZippedSeg.Length; i++)
            {
                numArray[i] = (uint) (random.Next(1, 0xfffffff) * -1);
                writer.Write('$');
                writer.Write(numArray[i]);
                writer.Write((uint) (9 + this.iZippedSeg[i].Length));
                writer.Write(this.iZippedSeg[i]);
                if (i == num4)
                {
                    writer.Write('#');
                    writer.Write((short) 0xf1);
                    writer.Write((byte) 0);
                    writer.Write((byte) 0x15);
                    writer.Write(Encoding.ASCII.GetBytes("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"));
                }
                if (i == num5)
                {
                    writer.Write('#');
                    writer.Write((short) 10);
                    writer.Write((byte) 0);
                    writer.Write((byte) 9);
                    writer.Write(this.iCID);
                }
            }
            num = (uint) (0x2000L + random.Next(0xfff));
            writer.Write('#');
            writer.Write((short) 0x81);
            writer.Write((byte) 1);
            writer.Write((byte) 9);
            writer.Write(num);
            writer.Write('$');
            writer.Write(num);
            writer.Write((uint) (9 + (numArray.Length * 4)));
            foreach (uint num7 in numArray)
            {
                writer.Write(num7);
            }
            if (File.Exists(this.iCoverFile))
            {
                FileStream stream2 = new FileStream(this.iCoverFile + ".tmp", FileMode.Open);
                byte[] buffer = new byte[stream2.Length];
                stream2.Read(buffer, 0, (int) stream2.Length);
                stream2.Close();
                num = (uint) (0x1000L + random.Next(0xfff));
                writer.Write('#');
                writer.Write((short) 130);
                writer.Write((byte) 1);
                writer.Write((byte) 10);
                writer.Write((byte) 1);
                writer.Write(num);
                writer.Write('$');
                writer.Write(num);
                writer.Write((uint) (9 + buffer.Length));
                writer.Write(buffer);
            }
            pbar.Maximum = this.iContent.Length * 5;
            pbar.Value = 0;
            this.GetPageOffsetS60(0x10, this.ACTUAL_WIDTH_S60_HORI, ref pbar, out numArray2);
            this.WritePageOffset(0x10, (byte) (this.ACTUAL_WIDTH_S60_HORI + 4), ref numArray2, ref writer, 1);
            numArray2.Initialize();
            this.GetPageOffsetS60(0x10, this.ACTUAL_WIDTH_S60_VERT, ref pbar, out numArray2);
            this.WritePageOffset(0x10, (byte) (this.ACTUAL_WIDTH_S60_VERT + 4), ref numArray2, ref writer, 1);
            numArray2.Initialize();
            this.GetPageOffsetS60(12, this.ACTUAL_WIDTH_S60_HORI, ref pbar, out numArray2);
            this.WritePageOffset(12, (byte) (this.ACTUAL_WIDTH_S60_HORI + 4), ref numArray2, ref writer, 1);
            numArray2.Initialize();
            this.GetPageOffsetS60(12, this.ACTUAL_WIDTH_S60_VERT, ref pbar, out numArray2);
            this.WritePageOffset(12, (byte) (this.ACTUAL_WIDTH_S60_VERT + 4), ref numArray2, ref writer, 1);
            numArray2.Initialize();
            this.GetPageOffsetSP(10, this.ACTUAL_WIDTH_SP, ref pbar, out numArray2);
            this.WritePageOffset(10, this.ACTUAL_WIDTH_SP, ref numArray2, ref writer, 5);
            writer.Write('#');
            writer.Write((short) 12);
            writer.Write((byte) 1);
            writer.Write((byte) 9);
            writer.Write((uint) (((uint) writer.BaseStream.Position) + 4));
            writer.Close();
            output.Close();
            result = "true";
            return true;
        }

        private void ParseOnePage(uint pPageNumber, byte pFontSize, uint pScreenWidth, ref ArrayList pPageoff, byte PID)
        {
            if (pPageNumber < pPageoff.Count)
            {
                string str = "";
                int num = 0;
                uint num2 = (uint) pPageoff[(int) pPageNumber];
                ArrayList list = new ArrayList();
                byte num3 = 0;
                if (PID == 1)
                {
                    num3 = 50;
                }
                if (PID == 5)
                {
                    num3 = 0x19;
                }
                for (byte i = 0; i < num3; i = (byte) (i + 1))
                {
                    str = str.Remove(0, str.Length);
                    string str2 = "";
                    byte num5 = 0;
                Label_0061:
                    if (num2 < this.iContent.Length)
                    {
                        str2 = this.iContent.Substring((int) num2, 1);
                    }
                    else
                    {
                        str2 = "\0";
                    }
                    switch (str2)
                    {
                        case "\t":
                        case "\0":
                            str2 = " ";
                            break;
                    }
                    byte num6 = this.CharWidth_S60(str2, pFontSize);
                    if (str2 == "\u2029")
                    {
                        num6 = 0;
                    }
                    if ((num6 + num5) <= pScreenWidth)
                    {
                        num5 = (byte) (num5 + num6);
                        num2++;
                        if (!(str2 == "\u2029"))
                        {
                            str = str + str2;
        &#