1: '
2: ' DotNetNuke® - http://www.dotnetnuke.com
3: ' Copyright (c) 2002-2008
4: ' by DotNetNuke Corporation
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: Imports ICSharpCode.SharpZipLib.Zip
21: Imports ICSharpCode.SharpZipLib.Checksums
22: Imports ICSharpCode.SharpZipLib.GZip
23: Imports System.IO
24: Imports System.Xml
25: Imports System.Xml.Serialization
26: Imports DotNetNuke.Modules.Admin.ResourceInstaller
27: Imports DotNetNuke.Entities.Modules.Definitions
28: Imports DotNetNuke.Services.Localization
29: Imports DotNetNuke.Framework.Providers
30:
31: Namespace DotNetNuke.Entities.Modules
32:
33: ''' -----------------------------------------------------------------------------
34: ''' Project : DotNetNuke
35: ''' Class : PaWriter
36: ''' -----------------------------------------------------------------------------
37: ''' <summary>
38: ''' The PaWriter class packages a Module as a Private Assembly.
39: ''' </summary>
40: ''' <remarks>
41: ''' </remarks>
42: ''' <history>
43: ''' [cnurse] 01/13/2005 created
44: ''' </history>
45: ''' -----------------------------------------------------------------------------
46: Public Class PaWriter
47:
48: #Region "Private Members"
49:
50: Private _CreateManifest As Boolean = True
51: Private _IncludeSource As Boolean = False
52: Private _ProgressLog As New PaLogger
53: Private _ResourceFileName As String
54: Private _SupportsProbingPrivatePath As Boolean = False
55: Private _ZipFile As String
56:
57: 'Source Folder of PA
58: Private _Folder As String
59: Private _AppCodeFolder As String
60: 'FUJI: Project Folder
61: Private _ProjectFolder As String
62: 'Name of PA
63: Private _Name As String
64:
65: 'List of Files to include in PA
66: Private _Files As New ArrayList
67:
68:
69: #End Region
70:
71: #Region "Constructors"
72:
73: Public Sub New()
74: Me.New(False, "")
75: End Sub
76:
77: Public Sub New(ByVal IncludeSource As Boolean, ByVal ZipFile As String)
78: _IncludeSource = IncludeSource
79: _ZipFile = ZipFile
80: End Sub
81:
82: Public Sub New(ByVal IncludeSource As Boolean, ByVal CreateManifest As Boolean, ByVal SupportsProbingPrivatePath As Boolean, ByVal ZipFile As String)
83: _CreateManifest = CreateManifest
84: _IncludeSource = IncludeSource
85: _SupportsProbingPrivatePath = SupportsProbingPrivatePath
86: _ZipFile = ZipFile
87: End Sub
88:
89: #End Region
90:
91: #Region "Protected Properties"
92:
93: Protected ReadOnly Property AppCodeFolder() As String
94: Get
95: Return _AppCodeFolder
96: End Get
97: End Property
98:
99: Protected ReadOnly Property CreateManifest() As Boolean
100: Get
101: Return _CreateManifest
102: End Get
103: End Property
104:
105: Protected ReadOnly Property Folder() As String
106: Get
107: Return _Folder
108: End Get
109: End Property
110: Protected ReadOnly Property ProjectFolder() As String
111: Get
112: Return _ProjectFolder
113: End Get
114: End Property
115:
116: Protected ReadOnly Property IncludeSource() As Boolean
117: Get
118: Return _IncludeSource
119: End Get
120: End Property
121:
122: Protected ReadOnly Property ResourceFileName() As String
123: Get
124: Return _ResourceFileName
125: End Get
126: End Property
127:
128: Protected ReadOnly Property SupportsProbingPrivatePath() As Boolean
129: Get
130: Return _SupportsProbingPrivatePath
131: End Get
132: End Property
133:
134:
135: #End Region
136:
137: #Region "Public Properties"
138:
139: Public ReadOnly Property ProgressLog() As PaLogger
140: Get
141: Return _ProgressLog
142: End Get
143: End Property
144:
145: Public Property ZipFile() As String
146: Get
147: Return _ZipFile
148: End Get
149: Set(ByVal Value As String)
150: _ZipFile = Value
151: End Set
152: End Property
153:
154: #End Region
155:
156: #Region "Private Methods"
157:
158: Private Sub AddFile(ByVal File As PaFileInfo, ByVal AllowUnsafeExtensions As Boolean)
159: Dim objPaFileInfo As PaFileInfo
160: Dim blnAdd As Boolean = True
161: For Each objPaFileInfo In _Files
162: If objPaFileInfo.FullName = File.FullName Then
163: blnAdd = False
164: Exit For
165: End If
166: Next
167: If Not AllowUnsafeExtensions Then
168: If Right(File.FullName, 3).ToLower = "dnn" Or Right(File.FullName, 10).ToLower = "dnn.config" Then blnAdd = False
169: End If
170:
171: If blnAdd Then
172: _Files.Add(File)
173: End If
174:
175: End Sub
176:
177: Private Sub AddFile(ByVal File As PaFileInfo)
178: AddFile(File, False)
179: End Sub
180:
181: Private Sub CreateDnnManifest(ByVal objDesktopModule As DesktopModuleInfo)
182:
183: Dim filename As String = ""
184: _Name = objDesktopModule.ModuleName
185:
186: 'Create Manifest Document
187: Dim xmlManifest As New XmlDocument
188:
189: 'Root Element
190: Dim nodeRoot As XmlNode = xmlManifest.CreateElement("dotnetnuke") 191: nodeRoot.Attributes.Append(XmlUtils.CreateAttribute(xmlManifest, "version", "3.0"))
192: nodeRoot.Attributes.Append(XmlUtils.CreateAttribute(xmlManifest, "type", "Module"))
193:
194: 'Folders Element
195: Dim nodeFolders As XmlNode = xmlManifest.CreateElement("folders") 196: nodeRoot.AppendChild(nodeFolders)
197:
198: 'Folder Element
199: Dim nodeFolder As XmlNode = xmlManifest.CreateElement("folder") 200: nodeFolders.AppendChild(nodeFolder)
201:
202: 'Desktop Module Info
203: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "name", _Name))
204: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "friendlyname", objDesktopModule.FriendlyName))
205: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "foldername", objDesktopModule.FolderName))
206: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "modulename", _Name))
207: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "description", objDesktopModule.Description))
208: If objDesktopModule.Version = Null.NullString Then
209: objDesktopModule.Version = "01.00.00"
210: End If
211: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "version", objDesktopModule.Version))
212: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "businesscontrollerclass", objDesktopModule.BusinessControllerClass))
213: If objDesktopModule.CompatibleVersions <> "" Then
214: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "compatibleversions", objDesktopModule.CompatibleVersions))
215: End If
216: If objDesktopModule.Dependencies <> "" Then
217: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "dependencies", objDesktopModule.Dependencies))
218: End If
219: If objDesktopModule.Permissions <> "" Then
220: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "permissions", objDesktopModule.Permissions))
221: End If
222: If SupportsProbingPrivatePath Then
223: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "supportsprobingprivatepath", SupportsProbingPrivatePath.ToString))
224: End If
225:
226: 'Add Source files
227: If IncludeSource Then
228: nodeFolder.AppendChild(XmlUtils.CreateElement(xmlManifest, "resourcefile", ResourceFileName))
229: End If
230:
231: 'Modules Element
232: Dim nodeModules As XmlNode = xmlManifest.CreateElement("modules") 233: nodeFolder.AppendChild(nodeModules)
234:
235: 'Get the Module Definitions for this Module
236: Dim objModuleDefinitionController As New ModuleDefinitionController
237: Dim arrModuleDefinitions As ArrayList = objModuleDefinitionController.GetModuleDefinitions(objDesktopModule.DesktopModuleID)
238:
239: 'Iterate through Module Definitions
240: For Each objModuleInfo As ModuleDefinitionInfo In arrModuleDefinitions
241: Dim nodeModule As XmlNode = xmlManifest.CreateElement("module") 242:
243: 'Add module definition properties
244: nodeModule.AppendChild(XmlUtils.CreateElement(xmlManifest, "friendlyname", objModuleInfo.FriendlyName))
245:
246: 'Add Cache properties
247: nodeModule.AppendChild(XmlUtils.CreateElement(xmlManifest, "cachetime", objModuleInfo.DefaultCacheTime.ToString))
248:
249: 'Get the Module Controls for this Module Definition
250: Dim arrModuleControls As ArrayList = ModuleControlController.GetModuleControls(objModuleInfo.ModuleDefID)
251:
252: 'Controls Element
253: Dim nodeControls As XmlNode = xmlManifest.CreateElement("controls") 254: nodeModule.AppendChild(nodeControls)
255:
256: 'Iterate through Module Controls
257: For Each objModuleControl As ModuleControlInfo In arrModuleControls
258: Dim nodeControl As XmlNode = xmlManifest.CreateElement("control") 259:
260: 'Add module control properties
261: XmlUtils.AppendElement(xmlManifest, nodeControl, "key", objModuleControl.ControlKey, False)
262: XmlUtils.AppendElement(xmlManifest, nodeControl, "title", objModuleControl.ControlTitle, False)
263:
264: XmlUtils.AppendElement(xmlManifest, nodeControl, "src", objModuleControl.ControlSrc, True)
265: XmlUtils.AppendElement(xmlManifest, nodeControl, "iconfile", objModuleControl.IconFile, False)
266: XmlUtils.AppendElement(xmlManifest, nodeControl, "type", objModuleControl.ControlType.ToString, True)
267: XmlUtils.AppendElement(xmlManifest, nodeControl, "helpurl", objModuleControl.HelpURL, False)
268:
269: If objModuleControl.SupportsPartialRendering Then
270: XmlUtils.AppendElement(xmlManifest, nodeControl, "supportspartialrendering", "true", False)
271: End If
272:
273: 'Add control Node to controls
274: nodeControls.AppendChild(nodeControl)
275:
276: 'Determine the filename for the Manifest file (It should be saved with the other Module files)
277: If filename = "" Then
278: filename = Folder & "\" & objDesktopModule.ModuleName + ".dnn"
279: End If
280: Next
281:
282: 'Add module Node to modules
283: nodeModules.AppendChild(nodeModule)
284: Next
285:
286: 'Files Element
287: Dim nodeFiles As XmlNode = xmlManifest.CreateElement("files") 288: nodeFolder.AppendChild(nodeFiles)
289:
290: 'Add the files
291: For Each file As PaFileInfo In _Files
292: Dim nodeFile As XmlNode = xmlManifest.CreateElement("file") 293:
294: 'Add file properties
295: XmlUtils.AppendElement(xmlManifest, nodeFile, "path", file.Path, False)
296: XmlUtils.AppendElement(xmlManifest, nodeFile, "name", file.Name, False)
297:
298: 'Add file Node to files
299: nodeFiles.AppendChild(nodeFile)
300: Next
301:
302: 'Add Root element to document
303: xmlManifest.AppendChild(nodeRoot)
304:
305: 'Save Manifest file
306: xmlManifest.Save(filename)
307:
308: End Sub
309:
310: Private Sub CreateFileList()
311:
312: 'Create the DirectoryInfo object
313: Dim folderInfo As New DirectoryInfo(Folder)
314:
315: 'Get the Project File in the folder
316: 'Dim files As FileInfo() = folderInfo.GetFiles("*.??proj") 317: 'FUJI: Add Flag SearchOption.AllDirectories
318: Dim files As FileInfo() = folderInfo.GetFiles("*.??proj", SearchOption.AllDirectories) 319:
320: If files.Length = 0 Then 'Assume Dynamic (App_Code based) Module
321:
322: 'Add the files in the DesktopModules Folder
323: ParseFolder(Folder, Folder)
324:
325: 'Add the files in the AppCode Folder
326: ParseFolder(AppCodeFolder, AppCodeFolder)
327:
328: Else 'WAP Project File is present
329:
330: 'Parse the Project files (probably only one)
331: For Each projFile As FileInfo In files
332: 'FUJI: Update folder
333: _ProjectFolder = projFile.DirectoryName
334: ParseProject(projFile)
335: Next
336:
337: End If
338: End Sub
339:
340: Private Function CreateZipFile() As String
341: Dim CompressionLevel As Integer = 9
342: Dim ZipFileShortName As String = _Name
343: Dim ZipFileName As String = _ZipFile
344: If ZipFileName = "" Then
345: ZipFileName = ZipFileShortName & ".zip"
346: End If
347: ZipFileName = Common.Globals.ApplicationMapPath & "\Install\Module\" & ZipFileName
348:
349: Dim strmZipFile As FileStream = Nothing
350: Try
351: ProgressLog.AddInfo(String.Format(Localization.GetString("LOG.PAWriter.CreateArchive"), ZipFileShortName)) 352: strmZipFile = File.Create(ZipFileName)
353: Dim strmZipStream As ZipOutputStream = Nothing
354: Try
355: strmZipStream = New ZipOutputStream(strmZipFile)
356: strmZipStream.SetLevel(CompressionLevel)
357: For Each PaFile As PaFileInfo In _Files
358: If File.Exists(PaFile.FullName) Then
359: FileSystemUtils.AddToZip(strmZipStream, PaFile.FullName, PaFile.Name, "")
360: ProgressLog.AddInfo(String.Format(Localization.GetString("LOG.PAWriter.SavedFile"), PaFile.Name)) 361: End If
362: Next
363: Catch ex As Exception
364: LogException(ex)
365: ProgressLog.AddFailure(String.Format(Localization.GetString("LOG.PAWriter.ERROR.SavingFile"), ex)) 366: Finally
367: If Not strmZipStream Is Nothing Then
368: strmZipStream.Finish()
369: strmZipStream.Close()
370: End If
371: End Try
372: Catch ex As Exception
373: LogException(ex)
374: ProgressLog.AddFailure(String.Format(Localization.GetString("LOG.PAWriter.ERROR.SavingFile"), ex)) 375: Finally
376: If Not strmZipFile Is Nothing Then
377: strmZipFile.Close()
378: End If
379: End Try
380:
381: Return ZipFileName
382: End Function
383:
384: #Region "WAP Methods"
385:
386: Private Sub AddFile(ByVal xmlFile As XmlNode)
387: Dim relPath As String = xmlFile.Attributes("Include").Value.Replace("/", "\") 388: Dim path As String = ""
389: Dim name As String = relPath
390: Dim fullPath As String = ProjectFolder
391: If relPath.LastIndexOf("\") > -1 Then 392: path = relPath.Substring(0, relPath.LastIndexOf("\")) 393: name = relPath.Replace(path & "\", "")
394: fullPath = fullPath & "\" & path
395: End If
396:
397: AddFile(New PaFileInfo(name, path, fullPath))
398: End Sub
399:
400: Private Sub AddSourceFiles(ByVal folderInfo As DirectoryInfo, ByVal fileType As String, ByRef resourcesFile As ZipOutputStream)
401:
402: 'Get the Source Files in the folder
403: Dim sourceFiles As FileInfo() = folderInfo.GetFiles(fileType)
404:
405: For Each sourceFile As FileInfo In sourceFiles
406: Dim filePath As String = sourceFile.FullName
407: Dim fileName As String = sourceFile.Name
408: Dim folderName As String = folderInfo.FullName.Replace(Folder, "")
409: If folderName <> "" Then
410: folderName += "\"
411: End If
412: If folderName.StartsWith("\") Then 413: folderName = folderName.Substring(1)
414: End If
415:
416: FileSystemUtils.AddToZip(resourcesFile, filePath, fileName, folderName)
417: Next
418:
419: End Sub
420:
421: Private Sub CreateResourceFile()
422:
423: 'Create the DirectoryInfo object
424: Dim folderInfo As New DirectoryInfo(Folder)
425: Dim filename As String = Folder & "\" & ResourceFileName
426:
427: 'Create Zip File to hold files
428: Dim resourcesFile As ZipOutputStream = New ZipOutputStream(File.Create(fileName))
429: resourcesFile.SetLevel(6)
430:
431: ParseFolder(folderInfo, resourcesFile)
432:
433: 'Add Resources File to File List
434: AddFile(New PaFileInfo(filename.Replace(Folder & "\", ""), "", Folder))
435:
436: 'Finish and Close Zip file
437: resourcesFile.Finish()
438: resourcesFile.Close()
439:
440: End Sub
441:
442: Private Sub ParseFolder(ByVal folder As DirectoryInfo, ByRef resourcesFile As ZipOutputStream)
443: 'Add the resource files
444: AddSourceFiles(folder, "*.sln", resourcesFile)
445: AddSourceFiles(folder, "*.??proj", resourcesFile)
446: AddSourceFiles(folder, "*.cs", resourcesFile)
447: AddSourceFiles(folder, "*.vb", resourcesFile)
448: AddSourceFiles(folder, "*.resx", resourcesFile)
449:
450: 'Check for Provider scripts
451: Dim objProviderConfiguration As ProviderConfiguration = ProviderConfiguration.GetProviderConfiguration("data") 452: For Each entry As DictionaryEntry In objProviderConfiguration.Providers
453: Dim objProvider As Provider = CType(entry.Value, Provider)
454: Dim providerName As String = objProvider.Name
455: AddSourceFiles(folder, "*." & providerName, resourcesFile)
456: Next
457:
458: 'Get the sub-folders in the folder
459: Dim folders As DirectoryInfo() = folder.GetDirectories()
460:
461: 'Recursively call ParseFolder to add files from sub-folder tree
462: For Each subfolder As DirectoryInfo In folders
463: If Not subfolder.Name.ToLower().Contains("_sgbak") Then 464: ParseFolder(subfolder, resourcesFile)
465: End If
466: Next
467: End Sub
468:
469: Private Sub ParseProject(ByVal projFile As FileInfo)
470:
471: Dim assemblyName As String = ""
472: Dim assemblyFolder As String = ApplicationMapPath & "/bin"
473:
474: 'Create and load the Project file xml
475: Dim xmlProject As New XmlDocument
476: xmlProject.Load(projFile.FullName)
477:
478: ' Create an XmlNamespaceManager to resolve the default namespace.
479: Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(xmlProject.NameTable)
480: nsmgr.AddNamespace("proj", "http://schemas.microsoft.com/developer/msbuild/2003") 481:
482: 'Get the Assembly Name and add to File List
483: Dim xmlSettings As XmlNode = xmlProject.DocumentElement.SelectSingleNode("proj:PropertyGroup/proj:AssemblyName", nsmgr) 484: assemblyName = xmlSettings.InnerText
485: AddFile(New PaFileInfo(assemblyName & ".dll", "", assemblyFolder))
486:
487: 'Add all the files that are classified as None
488: For Each xmlFile As XmlNode In xmlProject.DocumentElement.SelectNodes("proj:ItemGroup/proj:None", nsmgr) 489: AddFile(xmlFile)
490: Next
491:
492: 'Add all the files that are classified as Content
493: For Each xmlFile As XmlNode In xmlProject.DocumentElement.SelectNodes("proj:ItemGroup/proj:Content", nsmgr) 494: AddFile(xmlFile)
495: Next
496: End Sub
497:
498: #End Region
499:
500: #Region "App_Code Methods"
501:
502: Private Sub ParseFolder(ByVal folderName As String, ByVal rootPath As String)
503:
504: If Directory.Exists(folderName) Then
505: Dim folder As DirectoryInfo = New DirectoryInfo(folderName)
506:
507: 'Recursively parse the subFolders
508: Dim subFolders As DirectoryInfo() = folder.GetDirectories()
509: For Each subFolder As DirectoryInfo In subFolders
510: If Not subFolder.Name.ToLower().Contains("_sgbak") Then 511: ParseFolder(subFolder.FullName, rootPath)
512: End If
513: Next
514:
515: 'Add the Files in the Folder
516: Dim files As FileInfo() = folder.GetFiles()
517: For Each file As FileInfo In files
518: Dim path As String = folder.FullName.Replace(rootPath, "")
519: If path.StartsWith("\") Then 520: path = path.Substring(1)
521: End If
522: If folder.FullName.ToLower.Contains("app_code") Then 523: path = "[app_code]" + path
524: End If
525: AddFile(New PaFileInfo(file.Name, path, folder.FullName))
526: Next
527: End If
528:
529: End Sub
530:
531: #End Region
532:
533: #End Region
534:
535: #Region "Public Methods"
536:
537: Public Function CreatePrivateAssembly(ByVal DesktopModuleId As Integer) As String
538:
539: Dim Result As String = ""
540:
541: 'Get the Module Definition File for this Module
542: Dim objDesktopModuleController As New DesktopModuleController
543: Dim objModule As DesktopModuleInfo = objDesktopModuleController.GetDesktopModule(DesktopModuleId)
544: _Folder = Common.Globals.ApplicationMapPath & "\DesktopModules\" & objModule.FolderName
545: _AppCodeFolder = Common.Globals.ApplicationMapPath & "\App_Code\" & objModule.FolderName
546:
547: If IncludeSource Then
548: _ResourceFileName = objModule.ModuleName & "_Source.zip"
549: CreateResourceFile()
550: End If
551:
552: 'Create File List
553: CreateFileList()
554:
555: If CreateManifest Then
556: ProgressLog.StartJob(String.Format(Localization.GetString("LOG.PAWriter.CreateManifest"), objModule.FriendlyName)) 557: CreateDnnManifest(objModule)
558: ProgressLog.EndJob((String.Format(Localization.GetString("LOG.PAWriter.CreateManifest"), objModule.FriendlyName))) 559: End If
560:
561: 'Always add Manifest file to file list
562: AddFile(New PaFileInfo(objModule.ModuleName & ".dnn", "", Folder), True)
563:
564: ProgressLog.StartJob(String.Format(Localization.GetString("LOG.PAWriter.CreateZipFile"), objModule.FriendlyName)) 565: CreateZipFile()
566: ProgressLog.EndJob((String.Format(Localization.GetString("LOG.PAWriter.CreateZipFile"), objModule.FriendlyName))) 567:
568: Return Result
569: End Function
570:
571: #End Region
572:
573: End Class
574: End Namespace