DNN 研究路线图

首先我们从一个链接请求到达服务器开始讲起,来找出系统是如何处理各种要求的,从而整理出来我们需要的各个组件。

       我们首先看看在 web.config 这个网站的配置文件当中,有下面一段配置。它意味着系统在处理连接请求时首先会通过下列过滤器插件的处理。

 

 <httpModules>
      
<add name="UrlRewrite" type="DotNetNuke.HttpModules.UrlRewriteModule, DotNetNuke.HttpModules.UrlRewrite" />
      
<add name="Exception" type="DotNetNuke.HttpModules.ExceptionModule, DotNetNuke.HttpModules.Exception" />
      
<!-- add name="Authentication" type="DotNetNuke.HttpModules.AuthenticationModule, DotNetNuke.HttpModules.Authentication" / -->
      
<add name="UsersOnline" type="DotNetNuke.HttpModules.UsersOnlineModule, DotNetNuke.HttpModules.UsersOnline" />
      
<add name="ProfilePrototype" type="Microsoft.ScalableHosting.Profile.ProfileModule, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562" />
      
<add name="AnonymousIdentificationPrototype" type="Microsoft.ScalableHosting.Security.AnonymousIdentificationModule, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562" />
      
<add name="RoleManagerPrototype" type="Microsoft.ScalableHosting.Security.RoleManagerModule, MemberRole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7c773fb104e7562" />
      
<add name="DNNMembership" type="DotNetNuke.HttpModules.DNNMembershipModule, DotNetNuke.HttpModules.DNNMembership" />
      
<add name="Personalization" type="DotNetNuke.HttpModules.PersonalizationModule, DotNetNuke.HttpModules.Personalization" />
    
</httpModules>

 

 

首先处理连接请求的是 UrlRewriteModule 这个过滤器处理模块。这个模块的处理功能是将 DotNetNuke 的链接形式转化为正常+ & 的模式(DNN的鼻祖IBuySpy)。但是在这个模块当中也封装了一些其他的处理。我们来看看HttpModule.UrlRewrite 的一些功能。这个项目当中主要的结构在后面章节描述。

HttpModule.UrlRewrite 当中主要入口模块或者主要控制程序是UrlRewriteModule.vb 当中的UrlRewriteModule 类。它继承了 IHttpModule。这个类需要实现 OnBeginRequest 这个 function , 用来处理提交到服务器的链接。

Dim app As HttpApplication = CType(s, HttpApplication)
            
Dim requestedPath As String = app.Request.Url.AbsoluteUri
            
Dim Server As HttpServerUtility = app.Server
            
Dim Request As HttpRequest = app.Request
            
Dim Response As HttpResponse = app.Response

            
' URL validation 
            ' check for ".." escape characters commonly used by hackers to traverse the folder tree on the server
            ' the application should always use the exact relative location of the resource it is requesting
            'Dim strURL As String = Server.UrlDecode(Request.RawUrl)
            Dim strURL As String = Request.Url.AbsolutePath
            
Dim strDoubleDecodeURL As String = Server.UrlDecode(Server.UrlDecode(Request.RawUrl))
            
If strURL.IndexOf(".."<> -1 Or strDoubleDecodeURL.IndexOf(".."<> -1 Then
                
Throw New HttpException(404"Not Found")
            
End If

            
'fix for ASP.NET canonicalization issues http://support.microsoft.com/?kbid=887459
            If (Request.Path.IndexOf(Chr(92)) >= 0 Or System.IO.Path.GetFullPath(Request.PhysicalPath) <> Request.PhysicalPath) Then
                
Throw New HttpException(404"Not Found")
            
End If

            
'check if we are upgrading/installing
            If Request.Url.LocalPath.ToLower.EndsWith("install.aspx"Then
                
Exit Sub
            
End If

            
' Remove querystring if exists.. it gets added on later
            If (app.Request.Url.Query <> ""Then
                requestedPath 
= requestedPath.Replace(app.Request.Url.Query, "")
            
End If

            app.Context.Items.Add(
"UrlRewrite:OriginalUrl", app.Request.Url.AbsoluteUri)

            
Dim rules As Config.RewriterRuleCollection = Config.RewriterConfiguration.GetConfig().Rules

            
For i As Integer = 0 To rules.Count - 1
                
Dim lookFor As String = "^" & RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules(i).LookFor) & "$"
                
Dim re As Regex = New Regex(lookFor, RegexOptions.IgnoreCase)

                
If (re.IsMatch(requestedPath)) Then
                    
Dim sendTo As String = RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, re.Replace(requestedPath, rules(i).SendTo))
                    
Dim sesMatch As Match = re.Match(requestedPath)
                    
Dim sesUrlParams As String = sesMatch.Groups(2).Value

                    
If (sesUrlParams.Trim().Length > 0Then
                        sesUrlParams 
= sesUrlParams.Replace("\""/")
                        
Dim urlParams As String() = sesUrlParams.Split("/"c)

                        
For x As Integer = 1 To urlParams.Length - 1
                            
If (urlParams(x).Trim().Length > 0 And urlParams(x).ToLower <> glbDefaultPage.ToLower) Then
                                sendTo 
= sendTo & "&" & urlParams(x).Replace(".aspx""").Trim() & "="
                                
If (x < (urlParams.Length - 1)) Then
                                    x 
+= 1
                                    
If (urlParams(x).Trim <> ""Then
                                        sendTo 
= sendTo & urlParams(x).Replace(".aspx""")
                                    
End If
                                
End If
                            
End If
                        
Next
                    
End If
                    RewriterUtils.RewriteUrl(app.Context, sendTo)
                    
Exit For
                
End If
            
Next

            
Dim TabId As Integer = -1
            
Dim PortalId As Integer = -1
            
Dim DomainName As String = Nothing
            
Dim PortalAlias As String = Nothing
            
Dim objPortalAliasInfo As PortalAliasInfo

            
' get TabId from querystring ( this is mandatory for maintaining portal context for child portals )
            If Not (Request.QueryString("tabid"Is NothingThen
                TabId 
= Int32.Parse(Request.QueryString("tabid"))
            
End If
            
' get PortalId from querystring ( this is used for host menu options as well as child portal navigation )
            If Not (Request.QueryString("portalid"Is NothingThen
                PortalId 
= Int32.Parse(Request.QueryString("portalid"))
            
End If

            
' alias parameter can be used to switch portals
            If Not (Request.QueryString("alias"Is NothingThen
                
' check if the alias is valid
                If Not PortalSettings.GetPortalAliasInfo(Request.QueryString("alias")) Is Nothing Then
                    
' check if the domain name contains the alias
                    If InStr(1, Request.QueryString("alias"), DomainName, CompareMethod.Text) = 0 Then
                        
' redirect to the url defined in the alias
                        Response.Redirect(GetPortalDomainName(Request.QueryString("alias"), Request), True)
                    
Else ' the alias is the same as the current domain
                        PortalAlias = Request.QueryString("alias")
                    
End If
                
End If
            
End If

            
' parse the Request URL into a Domain Name token 
            DomainName = GetDomainName(Request)

            
' PortalId identifies a portal when set
            If PortalAlias Is Nothing Then
                
If PortalId <> -1 Then
                    PortalAlias 
= PortalSettings.GetPortalByID(PortalId, DomainName)
                
End If
            
End If

            
' TabId uniquely identifies a Portal
            If PortalAlias Is Nothing Then
                
If TabId <> -1 Then
                    
' get the alias from the tabid, but only if it is for a tab in that domain
                    PortalAlias = PortalSettings.GetPortalByTab(TabId, DomainName)
                    
If PortalAlias Is Nothing Or PortalAlias = "" Then
                        
'if the TabId is not for the correct domain
                        'see if the correct domain can be found and redirect it 
                        objPortalAliasInfo = PortalSettings.GetPortalAliasInfo(DomainName)
                        
If Not objPortalAliasInfo Is Nothing Then
                            
If app.Request.Url.AbsoluteUri.ToLower.StartsWith("https://"Then
                                strURL 
= "https://" & objPortalAliasInfo.HTTPAlias.Replace("*.""")
                            
Else
                                strURL 
= "http://" & objPortalAliasInfo.HTTPAlias.Replace("*.""")
                            
End If
                            
If strURL.ToLower.IndexOf(DomainName.ToLower()) = -1 Then
                                strURL 
+= app.Request.Url.PathAndQuery
                            
End If
                            Response.Redirect(strURL, 
True)
                        
End If
                    
End If
                
End If
            
End If

            
' else use the domain name
            If PortalAlias Is Nothing Or PortalAlias = "" Then
                PortalAlias 
= DomainName
            
End If
            
'using the DomainName above will find that alias that is the domainname portion of the Url
            'ie. dotnetnuke.com will be found even if zzz.dotnetnuke.com was entered on the Url
            objPortalAliasInfo = PortalSettings.GetPortalAliasInfo(PortalAlias)
            
If Not objPortalAliasInfo Is Nothing Then
                PortalId 
= objPortalAliasInfo.PortalID
            
End If

            
' if the portalid is not known
            If PortalId = -1 Then
                
If Not Request.Url.LocalPath.ToLower.EndsWith(glbDefaultPage.ToLower) Then
                    
' allows requests for aspx pages in custom folder locations to be processed
                    Exit Sub
                
Else
                    
'the domain name was not found so try using the host portal's first alias
                    If Convert.ToString(HostSettings("HostPortalId")) <> "" Then
                        PortalId 
= Convert.ToInt32(HostSettings("HostPortalId"))
                        
' use the host portal
                        Dim objPortalAliasController As New PortalAliasController
                        
Dim arrPortalAliases As ArrayList
                        arrPortalAliases 
= objPortalAliasController.GetPortalAliasArrayByPortalID(Integer.Parse(Convert.ToString(HostSettings("HostPortalId"))))
                        
If arrPortalAliases.Count > 0 Then
                            
'Get the first Alias
                            objPortalAliasInfo = CType(arrPortalAliases(0), PortalAliasInfo)
                            
If app.Request.Url.AbsoluteUri.ToLower.StartsWith("https://"Then
                                strURL 
= "https://" & objPortalAliasInfo.HTTPAlias.Replace("*.""")
                            
Else
                                strURL 
= "http://" & objPortalAliasInfo.HTTPAlias.Replace("*.""")
                            
End If
                            
If TabId <> -1 Then
                                strURL 
+= app.Request.Url.Query()
                            
End If
                            Response.Redirect(strURL, 
True)
                        
End If
                    
End If
                
End If
            
End If


            
If PortalId <> -1 Then
                
' load the PortalSettings into current context
                Dim _portalSettings As PortalSettings = New PortalSettings(TabId, objPortalAliasInfo)
                app.Context.Items.Add(
"PortalSettings", _portalSettings)
            
Else
                
' alias does not exist in database
                ' and all attempts to find another have failed
                'this should only happen if the HostPortal does not have any aliases
                Dim objStreamReader As StreamReader
                objStreamReader 
= File.OpenText(Server.MapPath("~/404.htm"))
                
Dim strHTML As String = objStreamReader.ReadToEnd
                objStreamReader.Close()
                strHTML 
= Replace(strHTML, "[DOMAINNAME]", DomainName)
                Response.Write(strHTML)
                Response.End()
            
End If

这一节代码有些长,需要对它进行重构。这段代码实现的主要功能有:

1、  验证 URL 正确性。

a)         检查是否有..”这种字符的存在,防止非法访问服务器目录。

b)        修改 Asp.net 中的一个漏洞。http://support.microsoft.com/?kbid=887459

c)        检查系统是是否在安装状态,这个部分我们省略掉。

2、  定义重写规则,这个部分我们在第二部分予以详细讲解。

3、  读取项目信息。这个部分原本不应该出现在重写模块。

a)         读取 TabID

b)        读取PortalId

c)        读取别称参数。别称用在在不同的 Portals 之间转换。

d)        解析域名。主要用在 Ip 地址与域名绑定上。通过这个功能实现了一个站点对应多个域名的功能。

e)         通过 tabid 取得 Portal 信息

f)         通过域名定义别称

g)        通过别称取得Portal信息

h)        通过 Portal id 获得protal信息

i)          通过上述操作,获得 Portalid 后取得 Portal 的设置信息,并且将设置信息保存在上下文当中。

关于 Portal 相关类结构我们在后面的章节进一步描述。

RewriterUtils 工具重写了 URL 之后,所有的请求将被传递给系统几个主要的入口页面。在 Portal 当中可以接受普通计算机发送过来的请求,但是也可以接受手机等其他特殊设备发送过来的请求。目前我们主要处理的是从普通计算机发送过来的请求。需要我们注意的有两点,第一、所有请求都有单一的页面入口处理。第二、Portal 程序都是以控件安装到我们的系统当中。

        下面,我们来看看 Default.aspx 是如何处理页面链接请求的

  1'
  2' DotNetNuke?- http://www.dotnetnuke.com
  3' Copyright (c) 2002-2006
  4' by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
  5'
  6' Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
  7' documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
  8' the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
  9' to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 10'
 11' The above copyright notice and this permission notice shall be included in all copies or substantial portions 
 12' of the Software.
 13'
 14' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
 15' TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 16' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
 17' CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
 18' DEALINGS IN THE SOFTWARE.
 19'
 20
 21Imports System.IO
 22Imports DotNetNuke.Entities.Tabs
 23Imports DotNetNuke.UI.Skins
 24
 25Namespace DotNetNukeNamespace DotNetNuke.Framework
 26    ''' -----------------------------------------------------------------------------
 27    ''' Project     : DotNetNuke
 28    ''' Class     : CDefault
 29    ''' 
 30    ''' -----------------------------------------------------------------------------
 31    ''' <summary>
 32    ''' 
 33    ''' </summary>
 34    ''' <remarks>
 35    ''' </remarks>
 36    ''' <history>
 37    '''     [sun1]    1/19/2004    Created
 38    ''' </history>
 39    ''' -----------------------------------------------------------------------------
 40    Public MustInherit Class CDefaultClass CDefault
 41
 42        Inherits DotNetNuke.Framework.PageBase
 43
 44        Public Comment As String = ""
 45        Public Title As String = ""
 46        Public Description As String = ""
 47        Public KeyWords As String = ""
 48        Public Copyright As String = ""
 49        Public Generator As String = ""
 50        Public Author As String = ""
 51
 52        Protected ScrollTop As System.Web.UI.HtmlControls.HtmlInputHidden
 53        Protected SkinError As System.Web.UI.WebControls.Label
 54        Protected SkinPlaceHolder As System.Web.UI.WebControls.PlaceHolder
 55
 56        Protected CSS As System.Web.UI.WebControls.PlaceHolder
 57        Protected FAVICON As System.Web.UI.WebControls.PlaceHolder
 58        Protected phDNNHead As System.Web.UI.WebControls.PlaceHolder
 59
 60Properties
 85
 86Private Methods
413
414Protected Methods
421
422Public Methods
444
445Event Handlers
576
577Web Form Designer Generated Code
585
586    End Class

587
588End Namespace

589
 

        Default.aspx.vb 文件当中DefaultPage继承了DotNetNuke.Framework.CDefault 主要实现了三个页面事件,4 sub 和一个比较主要的 function , 调用顺序如下:

 

我们首先来讲一讲 Page_Init 这个事件。

1、  调用InitializePage 功能,主要处理下列事件:

a)      从上下文获取 PortalSettings

b)      根据 Tab name 重定向到特定的 tab

c)      如果是第一访问页面,那么重载数据避免被客户端缓存。

d)      设置 page title stylesheet

e)      检查是否要显示 Assembly 版本

f)      设置背景图片

g)      设置 META tags, copyright, keywords and description

2、  装载皮肤控件

a)      如果 cookie 中有记载,就根据 cookie 设置装载控件。

b)      如果被分配了皮肤控件,就装载指定的控件

c)      为活动页面设置皮肤路径

3、  将皮肤装载到页面当中。

4、  调用客户端 API

在这个类当中另外响应事件是 Page_PreRender,主要调用了 ManageRequest 方法。

这个方法主要实现了联合管理和网站访问记录,可以暂时忽略。

    在这段代码当中继续起主要作用的是 Skin 当中的控件装载。接下来我们分析一下Skin 类的装载功能。

    我们先分析一下 Page_Init 事件处理过程:

 '
            ' CODEGEN: This call is required by the ASP.NET Web Form Designer.
            '
            InitializeComponent()

            
Dim objModules As New ModuleController
            
Dim objModule As ModuleInfo = Nothing
            
Dim ctlPane As Control
            
Dim blnLayoutMode As Boolean = Common.Globals.IsLayoutMode

            
Dim bSuccess As Boolean = True
            
' iterate page controls
            Dim ctlControl As Control
            
Dim objHtmlControl As HtmlControl
            
For Each ctlControl In Me.Controls
                
' load the skin panes,TopPanel,LeftPanel,ContentPanel,RightPanel,BottomPanel
                If TypeOf ctlControl Is HtmlControl Then
                    objHtmlControl 
= CType(ctlControl, HtmlControl)
                    
If Not objHtmlControl.ID Is Nothing Then
                        
Select Case objHtmlControl.TagName.ToUpper
                            
Case "TD""DIV""SPAN""P"
                                
' content pane
                                If ctlControl.ID <> "ControlPanel" Then
                                    PortalSettings.ActiveTab.Panes.Add(ctlControl.ID)
                                
End If
                        
End Select
                    
End If
                
End If
            
Next

            
'if querystring dnnprintmode=true, controlpanel will not be shown
            If Request.QueryString("dnnprintmode"<> "true" Then
                
' ControlPanel processing,如果是管理员角色则显示控制面板
                If (PortalSecurity.IsInRoles(PortalSettings.AdministratorRoleName.ToString) = True Or PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AdministratorRoles.ToString) = TrueThen
                    
Dim objControlPanel As UserControl = Nothing
                    
If Convert.ToString(PortalSettings.HostSettings("ControlPanel")) <> "" Then
                        
' load custom control panel
                        objControlPanel = CType(LoadControl("~/" & Convert.ToString(PortalSettings.HostSettings("ControlPanel"))), UserControl)
                    
End If
                    
If objControlPanel Is Nothing Then
                        
' load default control panel
                        objControlPanel = CType(LoadControl("~/" & glbDefaultControlPanel), UserControl)
                    
End If
                    
' inject ControlPanel control into skin
                    ctlPane = Me.FindControl("ControlPanel")
                    
If ctlPane Is Nothing Then
                        
Dim objForm As HtmlForm = CType(Me.Parent.FindControl("Form"), HtmlForm)
                        objForm.Controls.AddAt(
0, objControlPanel)
                    
Else
                        ctlPane.Controls.Add(objControlPanel)
                    
End If
                
End If
            
End If
            
            
If Not IsAdminControl() Then    ' master module

                
If PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AuthorizedRoles) Then

                    
' check portal expiry date
                    Dim blnExpired As Boolean = False
                    
If PortalSettings.ExpiryDate <> Null.NullDate Then
                        
If Convert.ToDateTime(PortalSettings.ExpiryDate) < Now() And PortalSettings.ActiveTab.ParentId <> PortalSettings.AdminTabId And PortalSettings.ActiveTab.ParentId <> PortalSettings.SuperTabId Then
                            blnExpired 
= True
                        
End If
                    
End If
                    
If Not blnExpired Then
                        
If (PortalSettings.ActiveTab.StartDate < Now And PortalSettings.ActiveTab.EndDate > Now) Or blnLayoutMode = True Then
                            
' process panes
                            If blnLayoutMode Then
                                
Dim strPane As String
                                
For Each strPane In PortalSettings.ActiveTab.Panes
                                    ctlPane 
= Me.FindControl(strPane)
                                    ctlPane.Visible 
= True

                                    
' display pane border
                                    If TypeOf ctlPane Is HtmlContainerControl Then
                                        
CType(ctlPane, HtmlContainerControl).Style("border-top"= "1px #CCCCCC dotted"
                                        
CType(ctlPane, HtmlContainerControl).Style("border-bottom"= "1px #CCCCCC dotted"
                                        
CType(ctlPane, HtmlContainerControl).Style("border-right"= "1px #CCCCCC dotted"
                                        
CType(ctlPane, HtmlContainerControl).Style("border-left"= "1px #CCCCCC dotted"
                                    
End If

                                    
' display pane name
                                    Dim ctlLabel As New Label
                                    ctlLabel.Text 
= "<center>" & strPane & "</center><br>"
                                    ctlLabel.CssClass 
= "SubHead"
                                    ctlPane.Controls.AddAt(
0, ctlLabel)
                                
Next
                            
End If

                            
' dynamically populate the panes with modules
                            If PortalSettings.ActiveTab.Modules.Count > 0 Then

                                
' loop through each entry in the configuration system for this tab
                                For Each objModule In PortalSettings.ActiveTab.Modules

                                    
' if user is allowed to view module and module is not deleted
                                    If PortalSecurity.IsInRoles(objModule.AuthorizedViewRoles) = True And objModule.IsDeleted = False Then

                                        
' if current date is within module display schedule or user is admin
                                        If (objModule.StartDate < Now And objModule.EndDate > Now) Or blnLayoutMode = True Then

                                            
' modules which are displayed on all tabs should not be displayed on the Admin or Super tabs
                                            '如果模块不是在所有页面或超级页面显示
                                            If objModule.AllTabs = False Or PortalSettings.ActiveTab.IsAdminTab = False Then

                                                
'查找模块的容器(TopPanel/LeftPanel/ContentPanel/..
                                                Dim parent As Control = Me.FindControl(objModule.PaneName)

                                                
If parent Is Nothing Then
                                                    
' the pane specified in the database does not exist for this skin
                                                    ' insert the module into the default pane instead
                                                    parent = Me.FindControl(glbDefaultPane)
                                                
End If

                                                
If Not parent Is Nothing Then
                                                    
' try to localize admin modules
                                                    If PortalSettings.ActiveTab.IsAdminTab Then
                                                        objModule.ModuleTitle 
= Services.Localization.Localization.LocalizeControlTitle(objModule.ModuleTitle, objModule.ControlSrc, "")
                                                    
End If

                                                    
'try to inject the module into the skin
                                                    '向模块内注入皮肤
                                                    Try
                                                        InjectModule(parent, objModule, PortalSettings)
                                                    
Catch ex As Exception
                                                        bSuccess 
= False
                                                    
End Try
                                                
Else             ' no ContentPane in skin
                                                    Dim lex As ModuleLoadException
                                                    lex 
= New ModuleLoadException(PANE_LOAD_ERROR)
                                                    Controls.Add(
New ErrorContainer(PortalSettings, MODULELOAD_ERROR, lex).Container)
                                                    LogException(lex)
                                                    Err.Clear()
                                                
End If

                                            
End If

                                        
End If

                                    
End If
                                
Next objModule
                            
End If
                        
Else
                            Skin.AddPageMessage(
Me"", TABACCESS_ERROR, UI.Skins.Controls.ModuleMessage.ModuleMessageType.YellowWarning)
                        
End If
                    
Else
                        Skin.AddPageMessage(
Me""String.Format(CONTRACTEXPIRED_ERROR, PortalSettings.PortalName, GetMediumDate(PortalSettings.ExpiryDate.ToString), PortalSettings.Email), UI.Skins.Controls.ModuleMessage.ModuleMessageType.RedError)
                    
End If
                
Else
                    Response.Redirect(AccessDeniedURL(TABACCESS_ERROR), 
True)
                
End If

            
Else    ' slave module

                
Dim ModuleId As Integer = -1
                
Dim Key As String = ""

                
' get ModuleId
                If Not IsNothing(Request.QueryString("mid")) Then
                    ModuleId 
= Int32.Parse(Request.QueryString("mid"))
                
End If

                
' get ControlKey
                If Not IsNothing(Request.QueryString("ctl")) Then
                    Key 
= Request.QueryString("ctl")
                
End If

                
' initialize moduleid for modulesettings
                If Not IsNothing(Request.QueryString("moduleid")) And (Key.ToLower = "module" Or Key.ToLower = "help"Then
                    ModuleId 
= Int32.Parse(Request.QueryString("moduleid"))
                
End If

                
If ModuleId <> -1 Then
                    
' get master module security settings
                    objModule = objModules.GetModule(ModuleId, PortalSettings.ActiveTab.TabID)
                    
If Not objModule Is Nothing Then
                        
If objModule.InheritViewPermissions Then
                            objModule.AuthorizedViewRoles 
= PortalSettings.ActiveTab.AuthorizedRoles
                        
End If
                    
End If
                
End If
                
If objModule Is Nothing Then
                    
' initialize object not related to a module
                    objModule = New ModuleInfo
                    objModule.ModuleID 
= ModuleId
                    objModule.ModuleDefID 
= -1
                    objModule.TabID 
= PortalSettings.ActiveTab.TabID
                    objModule.AuthorizedEditRoles 
= ""
                    objModule.AuthorizedViewRoles 
= ""
                
End If

                
' initialize moduledefid for modulesettings
                If Not IsNothing(Request.QueryString("moduleid")) And (Key.ToLower = "module" Or Key.ToLower = "help"Then
                    objModule.ModuleDefID 
= -1
                
End If

                
' override slave module settings
                If Request.QueryString("dnnprintmode"<> "true" Then
                    objModule.ModuleTitle 
= ""
                
End If
                objModule.Header 
= ""
                objModule.Footer 
= ""
                objModule.StartDate 
= DateTime.MinValue
                objModule.EndDate 
= DateTime.MaxValue
                objModule.PaneName 
= glbDefaultPane
                objModule.Visibility 
= VisibilityState.None
                objModule.Color 
= ""
                
If Request.QueryString("dnnprintmode"<> "true" Then
                    objModule.Alignment 
= "center"
                
End If
                objModule.Border 
= ""
                objModule.DisplayTitle 
= True
                objModule.DisplayPrint 
= False
                objModule.DisplaySyndicate 
= False

                
' get portal container for slave module
                Dim objSkin As SkinInfo = SkinController.GetSkin(SkinInfo.RootContainer, PortalSettings.PortalId, SkinType.Portal)
                
If Not objSkin Is Nothing Then
                    objModule.ContainerSrc 
= objSkin.SkinSrc
                
Else
                    objModule.ContainerSrc 
= "[G]" & SkinInfo.RootContainer & glbDefaultContainerFolder & glbDefaultContainer
                
End If
                objModule.ContainerSrc 
= SkinController.FormatSkinSrc(objModule.ContainerSrc, PortalSettings)
                objModule.ContainerPath 
= SkinController.FormatSkinPath(objModule.ContainerSrc)

                
' get the pane
                Dim parent As Control = Me.FindControl(objModule.PaneName)

                
' load the controls
                Dim objModuleControls As New ModuleControlController
                
Dim objModuleControl As ModuleControlInfo
                
Dim intCounter As Integer

                
Dim arrModuleControls As ArrayList = objModuleControls.GetModuleControlsByKey(Key, objModule.ModuleDefID)

                
For intCounter = 0 To arrModuleControls.Count - 1

                    objModuleControl 
= CType(arrModuleControls(intCounter), ModuleControlInfo)

                    
' initialize control values
                    objModule.ModuleControlId = objModuleControl.ModuleControlID
                    objModule.ControlSrc 
= objModuleControl.ControlSrc
                    objModule.ControlType 
= objModuleControl.ControlType
                    objModule.IconFile 
= objModuleControl.IconFile
                    objModule.HelpUrl 
= objModuleControl.HelpURL

                    
If Not Null.IsNull(objModuleControl.ControlTitle) Then
                        
' try to localize control title
                        objModule.ModuleTitle = Localization.LocalizeControlTitle(objModuleControl.ControlTitle, objModule.ControlSrc, Key)
                    
End If

                    
' verify that the current user has access to this control
                    Dim blnAuthorized As Boolean = True
                    
Select Case objModule.ControlType
                        
Case SecurityAccessLevel.Anonymous        ' anonymous
                        Case SecurityAccessLevel.View        ' view
                            If PortalSecurity.IsInRole(PortalSettings.AdministratorRoleName) = False And PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AdministratorRoles.ToString) = False Then
                                
If Not PortalSecurity.IsInRoles(objModule.AuthorizedViewRoles) Then
                                    blnAuthorized 
= False
                                
End If
                            
End If
                        
Case SecurityAccessLevel.Edit        ' edit
                            If PortalSecurity.IsInRole(PortalSettings.AdministratorRoleName) = False And PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AdministratorRoles.ToString) = False Then
                                
If Not PortalSecurity.IsInRoles(objModule.AuthorizedViewRoles) Then
                                    blnAuthorized 
= False
                                
Else
                                    
If Not PortalSecurity.HasEditPermissions(objModule.ModulePermissions) Then
                                        blnAuthorized 
= False
                                    
End If
                                
End If
                            
End If
                        
Case SecurityAccessLevel.Admin        ' admin
                            If PortalSecurity.IsInRole(PortalSettings.AdministratorRoleName) = False And PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AdministratorRoles.ToString) = False Then
                                blnAuthorized 
= False
                            
End If
                        
Case SecurityAccessLevel.Host        ' host
                            Dim objUserInfo As UserInfo = UserController.GetCurrentUserInfo
                            
If Not objUserInfo.IsSuperUser Then
                                blnAuthorized 
= False
                            
End If
                    
End Select

                    
If blnAuthorized Then
                        
'try to inject the module into the skin
                        Try
                            InjectModule(parent, objModule, PortalSettings)
                        
Catch ex As Exception
                            bSuccess 
= False
                        
End Try
                    
Else
                        Response.Redirect(AccessDeniedURL(MODULEACCESS_ERROR), 
True)
                    
End If

                
Next

            
End If

            
If Not blnLayoutMode Then
                CollapseUnusedPanes()
            
End If

            
If Not Request.QueryString("error"Is Nothing Then
                Skin.AddPageMessage(
Me, CRITICAL_ERROR, Server.HtmlEncode(Request.QueryString("error")), UI.Skins.Controls.ModuleMessage.ModuleMessageType.RedError)
            
End If

            
If Not (PortalSecurity.IsInRoles(PortalSettings.AdministratorRoleName) = True Or PortalSecurity.IsInRoles(PortalSettings.ActiveTab.AdministratorRoles.ToString) = TrueThen
                
' only display the warning to non-administrators (adminsitrators will see the errors)
                If Not bSuccess Then
                    Skin.AddPageMessage(
Me, MODULELOAD_WARNING, String.Format(MODULELOAD_WARNINGTEXT, PortalSettings.Email), UI.Skins.Controls.ModuleMessage.ModuleMessageType.YellowWarning)
                
End If
            
End If
 

1、InitializeComponent

2、迭代处理 Skin 界面当中所有的控件。因为在 Skin 界面当中会定义一些画板(画板-Pane,它分为5种画板类型TopPane,LeftPane,ContentPane,RightPane,BottomPane),并且将画板的 ID 记录在 PortalSettings.ActiveTab.Panes

3、判断是否是打印模式。如果是正常模式且有管理员权限需要显示 ControlPanel ,我们暂时不考虑这个部分

4、判断是否为主要处理模式

对于每个当前页面指定的模块找到相应的 Pane ,并且在装载 Title 时考虑全球化的问题

如果装载出错,处理页面异常。

5、判断是否为次要处理模式,主要为管理模块设置。

6、判断 blnLayoutMode 模式

在整个系统当中比较核心的一个方法是 InjectModule

这个函数在处理过程当中分为下面几个步骤:

1、装载容器

2、装载模块

Portal 信息类结构设计

Tab 类簇结构设计

HttpModule.UrlRewrite

Module 类簇设计

       Module 类簇设计是整个系统当中比较复杂的一个部分。它是 DotNetNuke 框架得以迅速扩展的基础。 Module 类簇主要包括下面几个部分:

1、  DesktopModule

 

2、  ModuleAction

 

3、   ModuleControl

 

4、  Module & ModuleSetting

posted @ 2006-11-22 14:24  风云  阅读(1859)  评论(0编辑  收藏  举报