Imports System.Xml Imports ICSharpCode.SharpZipLib.Zip Imports ICSharpCode.SharpZipLib.Checksums Imports System.IO #Region "Mailings" Public Class Mailings #Region "New" ''' ''' Create a new mailings class. ''' For each mailing call UserLogin, CreateMailing, and then the required mail pack and mailing list calls, and finally ProcessMailing. ''' ''' Public Sub New() End Sub #End Region #Region "Private properties" Private mMailingCollections As New Hashtable Private mMailings As New ArrayList Private mXMLFile As XMLFile Private mValidated As Boolean Private Class Collections Public Const Addresses As String = "addresses" Public Const AddressesData As String = "addressesData" Public Const AutoCorrectAddresses As String = "autoCorrectAddresses" Public Const CreateMailing As String = "createMailing" Public Const Designer As String = "designer" Public Const DesignerData As String = "designerData" Public Const DesignerImages As String = "designerImages" Public Const DesignerStoredImages As String = "designerStoredImages" Public Const DesignerText As String = "designerText" Public Const Mailing As String = "mailing" Public Const Mailings As String = "mailings" Public Const MailPack As String = "mailPack" Public Const MailPackVariableValues As String = "mailPackVariableValues" Public Const MailingList As String = "mailingList" Public Const MailingFilters As String = "mailingFilters" Public Const ProcessMailing As String = "processMailing" Public Const TemplateBackgroundRules As String = "templateBackgroundRules" Public Const TemplateData As String = "templateData" Public Const Templates As String = "templates" Public Const TemplateUseRules As String = "templateUseRules" Public Const TemplateVariableValues As String = "templateVariableValues" Public Const UserLogin As String = "userLogin" End Class Private Class Methods Public Const AddAddress As String = "addAddress" Public Const AddTemplateBackgroundRule As String = "addTemplateBackgroundRule" Public Const AddDesignerImage As String = "addDesignerImage" Public Const AddDesignerStoredImage As String = "addDesignerStoredImage" Public Const AddDesignerTemplate As String = "addDesignerTemplate" Public Const AddDesignerText As String = "addDesignerText" Public Const AddMailingFilter As String = "addMailingFilter" Public Const AddMailingListFile As String = "addMailingListFile" Public Const AddMailingListFromLibrary As String = "addMailingListFromLibrary" Public Const AddMailPackFromLibrary As String = "addMailPackFromLibrary" Public Const AddSelf As String = "addSelf" Public Const AddTemplateBackgroundFile As String = "addTemplateBackgroundFile" Public Const AddTemplateFile As String = "addTemplateFile" Public Const AddTemplateFromLibrary As String = "addTemplateFromLibrary" Public Const AddTemplateUseRule As String = "addTemplateUseRule" Public Const AutoCorrectAddresses As String = "autoCorrectAddresses" Public Const CreateMailing As String = "createMailing" Public Const ProcessMailing As String = "processMailing" Public Const SetMailingListProofOption As String = "setMailingListProofOption" Public Const SetMailPackVariableValue As String = "setMailPackVariableValue" Public Const SetTemplateVariableValue As String = "setTemplateVariableValue" Public Const UserLogin As String = "userLogin" End Class #End Region #Region "Constant helper strings" Public Class AddressField Public Const AddressLine1Original As String = "Address1" Public Const AddressLine2Original As String = "Address2" Public Const AddressLine3Original As String = "Address3" Public Const AddressLine4Original As String = "Address4" Public Const AddressLine5Original As String = "Address5" Public Const AddressLine6Original As String = "Address6" Public Const AddressLine1Output As String = "OutputAddress1" Public Const AddressLine2Output As String = "OutputAddress2" Public Const AddressLine3Output As String = "OutputAddress3" Public Const AddressLine4Output As String = "OutputAddress4" Public Const AddressLine5Output As String = "OutputAddress5" Public Const AddressLine6Output As String = "OutputAddress6" Public Const AddressLine1OutputClosed As String = "OutputAddress1Closed" Public Const AddressLine2OutputClosed As String = "OutputAddress2Closed" Public Const AddressLine3OutputClosed As String = "OutputAddress3Closed" Public Const AddressLine4OutputClosed As String = "OutputAddress4Closed" Public Const AddressLine5OutputClosed As String = "OutputAddress5Closed" Public Const AddressLine6OutputClosed As String = "OutputAddress6Closed" Public Const AddressLastLineOutput As String = "OutputAddressLast" Public Const AddressFullOutput As String = "OutputAddress" Public Const AddressPostalTariff As String = "OutputPostalTariff" Public Const CompanyName As String = "CompanyName" Public Const Custom1 As String = "Custom1" Public Const Custom2 As String = "Custom2" Public Const Custom3 As String = "Custom3" Public Const Custom4 As String = "Custom4" Public Const Custom5 As String = "Custom5" Public Const Custom6 As String = "Custom6" Public Const Custom7 As String = "Custom7" Public Const Custom8 As String = "Custom8" Public Const Custom9 As String = "Custom9" Public Const Custom10 As String = "Custom10" Public Const CustomerAddressIdentitiy As String = "CustomerAddressID" Public Const CustomerImportIdentitiy As String = "CustomerImportID" Public Const DirectLine As String = "DirectLine" Public Const Email As String = "Email" Public Const ExtraInfo As String = "ExtraInfo" Public Const Facsimile As String = "Facsimile" Public Const FirstName As String = "FirstName" Public Const FullName As String = "FullName" Public Const Initial As String = "Initial" Public Const JobTitle As String = "JobTitle" Public Const Mobile As String = "Mobile" Public Const Notes As String = "Notes" Public Const StreamPages1 As String = "StreamPages1" Public Const StreamPages2 As String = "StreamPages2" Public Const StreamPages3 As String = "StreamPages3" Public Const Surname As String = "Surname" Public Const Telephone As String = "Telephone" Public Const Title As String = "Title" Public Const UseForProof As String = "UseForProof" End Class Public Class PartDisplayName Public Class Postcard Public Const BackgroundPhoto As String = "Background photo" Public Const Message As String = "Message" End Class Public Class GreetingsCard Public Const BackgroundPhoto As String = "Background photo" Public Const From As String = "From" Public Const Greeting As String = "Greeting" Public Const [To] As String = "To" End Class End Class Public Class TemplateLayout Public Class Postcard Public Const PostcardA5LeftAddress As String = "Postcard A5 left address" Public Const PostcardA5RightAddress As String = "Postcard A5 right address" Public Const PostcardA6LeftAddress As String = "Postcard A6 left address" Public Const PostcardA6RightAddress As String = "Postcard A6 right address" End Class Public Class GreetingsCard Public Const Landscape As String = "Landscape" Public Const LandscapeWithBorder As String = "Landscape with border" Public Const Portrait As String = "Portrait" Public Const PortraitWithBorder As String = "Portrait with border" End Class End Class #End Region #Region "Enumerations" Public Enum ProductType [Default] A4Letter GreetingCard Postcard A3FoldedSheet SMS A5Postcard A6Postcard End Enum Public Enum DeliveryType [Default] First FirstDotpost FirstNoReturns FirstNoReturnsDotpost FirstNoReturnsProofPerAddress FirstProofPerAddress FirstReturns FirstReturnsDotpost FirstReturnsOwn FirstReturnsOwnDotpost FirstReturnsProofPerAddress FirstReturnsOwnProofPerAddress Standard StandardDotpost StandardNoReturns StandardNoReturnsDotpost StandardNoReturnsProofPerAddress StandardProofPerAddress StandardReturns StandardReturnsDotpost StandardReturnsOwn StandardReturnsOwnDotpost StandardReturnsOwnProofPerAddress StandardReturnsProofPerAddress Courier End Enum Public Enum AddressNameFormat [Default] Full_Name Firstname_Surname Title_Initial_Surname Title_Surname Title_Firstname_Surname End Enum Public Class EnvelopeSize ''' ''' Use the envelope defined on the default mailing options for the product ''' ''' Public Const [Default] As String = "Default" ''' ''' Use C4 window envelopes only ''' ''' Public Const C4 As String = "C4" ''' ''' Use C5 standard envelopes ''' ''' Public Const C5 As String = "C5" ''' ''' Use C5 window envelopes only ''' ''' Public Const C5Window As String = "C5Window" ''' ''' Use a custom envelope ''' ''' Public Const Custom As String = "Custom" ''' ''' Use a custom envelope and hide the address panel on the document ''' ''' Public Const CustomNoPanel As String = "CustomNoPanel" ''' ''' Use a custom envelope, hide the address panel on the document and skip the envelope proof ''' ''' Public Const CustomNoPanelSkip As String = "CustomNoPanelSkip" ''' ''' Use a custom envelope but skip the envelope proof ''' ''' Public Const CustomSkip As String = "CustomSkip" ''' ''' Use standard envelopes ''' ''' Public Const Standard As String = "Standard" ''' ''' Use a standard envelope and hide the address panel on the document ''' ''' Public Const StandardNoPanel As String = "StandardNoPanel" ''' ''' Use a standard envelope, hide the address panel on the document and skip the envelope proof ''' ''' Public Const StandardNoPanelSkip As String = "StandardNoPanelSkip" ''' ''' Use standard envelope and skip envelope proof when own return address is supplied ''' ''' Public Const StandardSkip As String = "StandardSkip" End Class Public Enum PaymentMethod [Default] Invoice Topup End Enum Public Enum DocumentType [Default] A4Letter GreetingCardA5 OuterEnvelope PostcardA5 PostcardA6 PostcardA5Right PostcardA6Right A44PageBooklet SMS End Enum Public Enum AddressFontCode [Default] Arial_10 Arial_11 Arial_12 Arial_13 Arial_14 Courier_10 Courier_11 Courier_12 Courier_13 Courier_14 Gotham_9 Gotham_10 Gotham_12 Helvetica_10 Helvetica_11 Helvetica_12 Helvetica_13 Helvetica_14 MetaOT_10 MetaOT_11 MetaOT_12 Trebuchet_10 Trebuchet_11 Trebuchet_12 Verdana_10 Verdana_11 Verdana_12 End Enum Public Enum TemplateType [Default] Document Preformatted_Stream End Enum Public Enum FontName [Default] Arial Courier Gotham_Narrow_Book Goudy_Old_Style Helvetica Lucida_Handwriting MetaOT_Normal MGillSansLight Party_LET Times_New_Roman Trebuchet_MS Verdana End Enum Public Enum TextJustification [Default] Center Full Left Right End Enum Public Enum ImageFitOption Crop Resize_to_fit End Enum Public Enum DataFormat Automatic Excel CSV Tab_separated Delimited Fixed_width End Enum Public Enum CorrectionMethod All Cost Original End Enum Public Enum ProofOption Clear FirstMidLast Last Longest LongestCustomData End Enum Public Enum RuleDataFormat [Boolean] [Date] Numeric Text End Enum Public Enum FromEquation Greater_than Greater_than_or_equals Equals Less_than Less_than_or_equals Not_equal_to [Like] Not_like End Enum Public Enum ToEquation Less_than Less_than_or_equals None End Enum #End Region #Region "Mailing calls" #Region "Login" ''' ''' Supply the login details for processing this mailing. ''' ''' ''' ''' ''' Public Sub UserLogin(ByVal LoginName As String, ByVal Password As String, ByVal EncryptedPassword As Boolean) SaveCall(Methods.UserLogin, Collections.UserLogin, LoginName, Password, EncryptedPassword) End Sub #End Region #Region "Create Mailing" ''' ''' Create a a mailing ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' Public Sub CreateMailing(ByVal CustomerApplication As String, ByVal ProductType As ProductType, ByVal MailingName As String, ByVal MailingDescription As String, _ ByVal IsMono As Boolean, ByVal IsDuplex As Boolean, ByVal DeliveryType As DeliveryType, ByVal CourierDeliveryToSelf As Boolean, _ ByVal DespatchASAP As Boolean, ByVal DespatchDate As Date, ByVal AddressNamePrefix As String, _ ByVal AddressNameFormat As AddressNameFormat, ByVal DiscountCode As String, ByVal MinEnvelopeSize As String) SaveCall(Methods.CreateMailing, Collections.CreateMailing, _ CustomerApplication, ProductType, MailingName, MailingDescription, _ IsMono, IsDuplex, DeliveryType, CourierDeliveryToSelf, _ DespatchASAP, DespatchDate, AddressNamePrefix, _ AddressNameFormat, DiscountCode, MinEnvelopeSize) End Sub ''' ''' Add a mailing filter. For use by corporate accounts only. ''' ''' ''' ''' Public Sub AddMailingFilter(ByVal CategoryName As String, ByVal FilterValue As String) SaveCall(Methods.AddMailingFilter, Collections.MailingFilters, _ CategoryName, FilterValue) End Sub #End Region #Region "Mail pack" ''' ''' Add a template file to a mailing. ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' Public Sub AddTemplateFile(ByVal TemplateName As String, ByVal FileName As String, ByVal FileData As Byte(), ByVal DocumentType As DocumentType, _ ByVal AddressedDocument As Boolean, ByVal AddressFontCode As AddressFontCode, ByVal TemplateType As TemplateType, _ ByVal BackgroundName As String, ByVal CanBeginOnBack As Boolean, ByVal NextTemplateCanBeginOnBack As Boolean, _ ByVal ProtectedAreaPassword As String, ByVal EncryptionPassword As String, ByVal BleedSupplied As Boolean, ByVal Copies As Integer, _ ByVal Instances As Integer, ByVal InstancePageNumbers As String, ByVal CycleInstancesOnCopies As Boolean) ' Fix instances if passed as zero, must be 1 or higher for ZML schema 'If Instances <= 0 Then Instances = 1 SaveCall(Methods.AddTemplateFile, Collections.TemplateData, _ TemplateName, FileName, FileData, DocumentType, _ AddressedDocument, AddressFontCode, TemplateType, _ BackgroundName, CanBeginOnBack, NextTemplateCanBeginOnBack, _ ProtectedAreaPassword, EncryptionPassword, BleedSupplied, Copies, _ Instances, InstancePageNumbers, CycleInstancesOnCopies) End Sub ''' ''' Add background file to a template. ''' ''' ''' ''' ''' ''' Public Sub AddTemplateBackgroundFile(ByVal BackgroundName As String, ByVal FileName As String, ByVal FileData As Byte(), _ ByVal EncryptionPassword As String) SaveCall(Methods.AddTemplateBackgroundFile, Collections.TemplateData, _ BackgroundName, FileName, FileData, _ EncryptionPassword) End Sub ''' ''' Add a template from the library. ''' ''' ''' ''' Public Sub AddTemplateFromLibrary(ByVal TemplateName As String, ByVal Copies As Integer) SaveCall(Methods.AddTemplateFromLibrary, Collections.TemplateData, _ TemplateName, Copies) End Sub ''' ''' Add mail pack from library. ''' ''' ''' Public Sub AddMailPackFromLibrary(ByVal MailPackName As String) SaveCall(Methods.AddMailPackFromLibrary, Collections.TemplateData, _ MailPackName) End Sub ''' ''' Add a designer template. ''' ''' ''' ''' ''' ''' ''' ''' Public Sub AddDesignerTemplate(ByVal TemplateLayout As String, ByVal DocumentType As DocumentType, ByVal AddressFontCode As AddressFontCode, _ ByVal BleedSupplied As Boolean, ByVal Copies As Integer, ByVal SkipPreviewImageGeneration As Boolean) SaveCall(Methods.AddDesignerTemplate, Collections.Designer, _ TemplateLayout, DocumentType, AddressFontCode, _ BleedSupplied, Copies, SkipPreviewImageGeneration) End Sub ''' ''' Add a designer image. ''' ''' ''' ''' ''' ''' ''' Public Sub AddDesignerImage(ByVal PartDisplayName As String, ByVal FileName As String, ByVal FileData As Byte(), _ ByVal ImageRotation As Double, ByVal ImageFitOption As ImageFitOption) SaveCall(Methods.AddDesignerImage, Collections.DesignerImages, _ PartDisplayName, FileName, FileData, _ ImageRotation, ImageFitOption) End Sub ''' ''' Add designer stored image. ''' ''' ''' ''' ''' ''' Public Sub AddDesignerStoredImage(ByVal PartDisplayName As String, ByVal ImageName As String, ByVal ImageRotation As Double, ByVal ImageFitOption As ImageFitOption) SaveCall(Methods.AddDesignerStoredImage, Collections.DesignerStoredImages, _ PartDisplayName, ImageName, ImageRotation, ImageFitOption) End Sub ''' ''' Add designer text. ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' Public Sub AddDesignerText(ByVal PartDisplayName As String, ByVal TextContent As String, ByVal FontSize As Integer, ByVal FontName As FontName, _ ByVal Bold As Boolean, ByVal Italic As Boolean, ByVal Underline As Boolean, ByVal TextJustification As TextJustification, _ ByVal FontColourRed As Integer, ByVal FontColourGreen As Integer, ByVal FontColourBlue As Integer) SaveCall(Methods.AddDesignerText, Collections.DesignerText, _ PartDisplayName, TextContent, FontSize, FontName, _ Bold, Italic, Underline, TextJustification, _ FontColourRed, FontColourGreen, FontColourBlue) End Sub ''' ''' Set a variable value for all templates containing the variable in the mail pack. ''' ''' ''' ''' Public Sub SetMailPackVariableValue(ByVal VariableName As String, ByVal VariableValue As String) SaveCall(Methods.SetMailPackVariableValue, Collections.TemplateData, _ VariableName, VariableValue) End Sub ''' ''' Set template variable value. ''' ''' ''' ''' Public Sub SetTemplateVariableValue(ByVal VariableName As String, ByVal VariableValue As String) SaveCall(Methods.SetTemplateVariableValue, Collections.TemplateData, _ VariableName, VariableValue) End Sub ''' ''' Add a template use rule. ''' ''' ''' ''' ''' ''' ''' ''' ''' Public Sub AddTemplateUseRule(ByVal AndGroup As String, ByVal AddressField As String, _ ByVal DataFormat As RuleDataFormat, ByVal FromEquation As FromEquation, ByVal FromData As String, _ ByVal ToEquation As ToEquation, ByVal ToData As String) SaveCall(Methods.AddTemplateUseRule, Collections.TemplateData, _ AndGroup, AddressField, _ DataFormat, FromEquation, FromData, _ ToEquation, ToData) End Sub ''' ''' Add a template background rule. ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' Public Sub AddTemplateBackgroundRule(ByVal BackgroundName As String, ByVal AndGroup As String, _ ByVal AddressField As String, ByVal DataFormat As RuleDataFormat, ByVal FromEquation As FromEquation, _ ByVal FromData As String, ByVal ToEquation As ToEquation, ByVal ToData As String) SaveCall(Methods.AddTemplateBackgroundRule, Collections.TemplateData, _ BackgroundName, AndGroup, _ AddressField, DataFormat, FromEquation, _ FromData, ToEquation, ToData) End Sub #End Region #Region "Mailing list" ''' ''' Add a mailing list file. ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' Public Sub AddMailingListFile(ByVal FileName As String, ByVal FileData As Byte(), ByVal DataFormat As DataFormat, ByVal HasHeaders As Boolean, _ ByVal SheetName As String, ByVal MappingDelimiter As String, ByVal MappingFixedWidthChars As String, ByVal MappingName As String) SaveCall(Methods.AddMailingListFile, Collections.AddressesData, _ FileName, FileData, DataFormat, HasHeaders, _ SheetName, MappingDelimiter, MappingFixedWidthChars, MappingName) End Sub ''' ''' Add a mailing list from the library. ''' ''' ''' Public Sub AddMailingListFromLibrary(ByVal MailingListName As String) SaveCall(Methods.AddMailingListFromLibrary, Collections.AddressesData, _ MailingListName) End Sub ''' ''' Add an address. ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' Public Sub AddAddress(ByVal Address1 As String, ByVal Address2 As String, ByVal Address3 As String, ByVal Address4 As String, ByVal Address5 As String, ByVal Address6 As String, _ ByVal UseForProof As Boolean, ByVal Title As String, ByVal FirstName As String, ByVal Surname As String, ByVal Fullname As String, ByVal JobTitle As String, _ ByVal CompanyName As String, ByVal Email As String, ByVal Telephone As String, ByVal DirectLine As String, ByVal Mobile As String, ByVal Facsimile As String, _ ByVal ExtraInfo As String, ByVal Notes As String, ByVal CustomerAddressID As String, ByVal CustomerImportID As String, _ ByVal StreamPages1 As Integer, ByVal StreamPages2 As Integer, ByVal StreamPages3 As Integer, _ ByVal Custom1 As String, ByVal Custom2 As String, ByVal Custom3 As String, ByVal Custom4 As String, ByVal Custom5 As String, _ ByVal Custom6 As String, ByVal Custom7 As String, ByVal Custom8 As String, ByVal Custom9 As String, ByVal Custom10 As String) SaveCall(Methods.AddAddress, Collections.AddressesData, _ Address1, Address2, Address3, Address4, Address5, Address6, _ UseForProof, Title, FirstName, Surname, Fullname, JobTitle, _ CompanyName, Email, Telephone, DirectLine, Mobile, Facsimile, _ ExtraInfo, Notes, CustomerAddressID, CustomerImportID, _ StreamPages1, StreamPages2, StreamPages3, _ Custom1, Custom2, Custom3, Custom4, Custom5, _ Custom6, Custom7, Custom8, Custom9, Custom10) End Sub ''' ''' Add self to the mailing. ''' ''' Public Sub AddSelf() SaveCall(Methods.AddSelf, Collections.MailingList, _ True) End Sub ''' ''' Auto correct all the addresses added to the mailing. ''' ''' ''' Public Sub AutoCorrectAddresses(ByVal CorrectionMethod As CorrectionMethod) SaveCall(Methods.AutoCorrectAddresses, Collections.AutoCorrectAddresses, _ CorrectionMethod) End Sub ''' ''' Set the mailing list proof option. ''' ''' ''' Public Sub SetMailingListProofOption(ByVal ProofOption As ProofOption) SaveCall(Methods.SetMailingListProofOption, Collections.MailingList, _ ProofOption) End Sub #End Region #Region "Process mailing" ''' ''' Flag the mailing as ready to process. ''' This must be called for each mailing and once called no more data can be added to the mailing. ''' To add another mailing start by calling UserLogin. ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' ''' Public Sub ProcessMailing(ByVal CustomerApplication As String, ByVal Submit As Boolean, ByVal PartialProcess As Boolean, ByVal MaxPriceExVAT As Double, _ ByVal POReference As String, ByVal PaymentMethod As PaymentMethod, ByVal SkipPreviewImageGeneration As Boolean, _ ByVal EmailSuccessList As String, ByVal EmailErrorList As String, ByVal HttpPostOnSuccess As String, ByVal HttpPostOnError As String) SaveCall(Methods.ProcessMailing, Collections.ProcessMailing, _ CustomerApplication, Submit, PartialProcess, MaxPriceExVAT, _ POReference, PaymentMethod, SkipPreviewImageGeneration, _ EmailSuccessList, EmailErrorList, HttpPostOnSuccess, HttpPostOnError) ' Mailing complete, so add to the mailing collection mMailings.Add(mMailingCollections) ' Reset the calls collection for the new mailing mMailingCollections = New Hashtable End Sub #End Region #End Region #Region "Save call" ''' ''' Class to hold method name and collection of parameters ''' ''' Private Class MethodParams Public MethodName As String Public ParameterValues As ArrayList ''' ''' Create a new method params object ''' ''' ''' ''' Public Sub New(ByVal MethodName As String, ByVal ParameterValues As ArrayList) Me.MethodName = MethodName Me.ParameterValues = ParameterValues End Sub End Class ''' ''' Save parameters in an array list for processing later ''' ''' ''' Private Sub SaveCall(ByVal ParamArray Parameters As Object()) Dim oParams As New ArrayList Dim sMethodName As String = "" Dim sCollection As String = "" For iLoop As Integer = 0 To Parameters.Length - 1 If iLoop = 0 Then ' Get method name sMethodName = CStr(Parameters(0)) ElseIf iLoop = 1 Then sCollection = CStr(Parameters(1)) Else oParams.Add(Parameters(iLoop)) End If Next ' Add this call to a collection of calls to the method If Not mMailingCollections.ContainsKey(sCollection) Then mMailingCollections.Add(sCollection, New ArrayList) Dim oMethods As ArrayList = CType(mMailingCollections(sCollection), ArrayList) oMethods.Add(New MethodParams(sMethodName, oParams)) ' Flag file as not validated mValidated = False End Sub #End Region #Region "Create zip" Private mMethodsPopulated As Boolean Private mMethods As Hashtable Private mFiles As Hashtable ''' ''' Return the XML document string, populated in the Validate function ''' ''' ''' ''' Public ReadOnly Property XMLFileString() As String Get If mXMLFile Is Nothing Then Return "" Else Return mXMLFile.XMLDocument.OuterXml End If End Get End Property ''' ''' Create the zip file. ''' To use this override you must call the Validate function first. ''' ''' ''' ''' Public Function CreateZip(ByVal XMLFileName As String) As Byte() If Not mValidated Then Throw New Exception("The Validate function must be called first before using CreateZip with supplying the XML Schema URL.") Return CreateZip(XMLFileName, "") End Function ''' ''' Create the zip file containing the XML file. ''' Note that if the Validate function has not been called first then an exception will be thrown if a validation error occurs. ''' ''' ''' ''' ''' Public Function CreateZip(ByVal XMLFileName As String, ByVal XMLSchemaURL As String) As Byte() Dim sErrorMessage As String = "" ' Get the XML If Not mValidated AndAlso Not Validate(XMLSchemaURL, sErrorMessage) Then Throw New Exception(sErrorMessage) ' Create the zip file Dim oZip As New Zip ' Add files For Each sFileName As String In mFiles.Keys oZip.Add(sFileName, CType(mFiles(sFileName), Byte())) Next ' Add the XML file oZip.Add(XMLFileName, System.Text.Encoding.UTF8.GetBytes(Me.XMLFileString)) ' Return the zip as a byte array Return oZip.ToZip End Function ''' ''' Create the XML file, return as a string ''' ''' ''' ''' ''' Public Function Validate(ByVal XMLSchemaURL As String, ByRef ErrorMessage As String) As Boolean Dim oXMLTextReader As XmlTextReader Try ' Extract method from XML schema (only needed on first call as then cached) If mMethodsPopulated = False Then oXMLTextReader = New XmlTextReader(XMLSchemaURL) oXMLTextReader.WhitespaceHandling = WhitespaceHandling.None Dim sNodeName As String ' Read method elements into collection Dim oComplexType As New ArrayList Dim oSimpleTypes As New ArrayList While oXMLTextReader.Read() If oXMLTextReader.NodeType = XmlNodeType.Element Then Select Case oXMLTextReader.Name Case "xs:complexType" sNodeName = oXMLTextReader.GetAttribute("name") If Not sNodeName Is Nothing AndAlso sNodeName <> "" Then If Not oComplexType.Contains(sNodeName) Then oComplexType.Add(sNodeName) End If Case "xs:simpleType" oSimpleTypes.Add(oXMLTextReader.GetAttribute("name")) End Select End If End While oXMLTextReader.Close() ' Open again and loop through node structure oXMLTextReader = New XmlTextReader(XMLSchemaURL) oXMLTextReader.WhitespaceHandling = WhitespaceHandling.None mMethods = New Hashtable Do While oXMLTextReader.Read() If oXMLTextReader.NodeType = XmlNodeType.Element Then sNodeName = oXMLTextReader.GetAttribute("name") If Not sNodeName Is Nothing AndAlso sNodeName <> "" AndAlso oXMLTextReader.Name = "xs:complexType" Then ReadComplexType(sNodeName, oXMLTextReader, oComplexType, oSimpleTypes) End If End If Loop oXMLTextReader.Close() oXMLTextReader = Nothing ' Flag as populated so do not have to extract again mMethodsPopulated = True End If ' Clear files collection mFiles = New Hashtable ' Create XML file mXMLFile = New XMLFile mXMLFile.AddRootNode(Collections.Mailings, XMLSchemaURL, XMLSchemaURL & " " & XMLSchemaURL) ' Loop though mailings For Each Me.mMailingCollections In Me.mMailings ' Set current node to the mailings root node mXMLFile.CurrentNode = mXMLFile.RootNode ' Add the mailing node Dim oMailingNode As XmlNode = mXMLFile.AddNode(Collections.Mailing) ' Add the user login ProcessCollection(Collections.UserLogin, False, True) ' Add the create mailing node and any mailing filters mXMLFile.CurrentNode = oMailingNode ProcessCollection(Collections.CreateMailing, False, True) Dim oCreateMailingNode As XmlNode = mXMLFile.CurrentNode ' Add any mailing filters suppied under the create mailing node mXMLFile.CurrentNode = oCreateMailingNode If mMailingCollections.ContainsKey(Collections.MailingFilters) Then ProcessCollection(Collections.MailingFilters, False) ' Add the mail pack node mXMLFile.CurrentNode = oMailingNode Dim oMailPackNode As XmlNode = mXMLFile.AddNode(Collections.MailPack) ' Add any designer data (if any nodes for the collection exist on the mailing) If mMailingCollections.ContainsKey(Collections.Designer) Then Dim oDesignerNode As XmlNode = mXMLFile.AddNode(Collections.Designer) ProcessCollection(Collections.Designer, True) mXMLFile.CurrentNode = oDesignerNode Dim oDesignerDataNode As XmlNode = mXMLFile.AddNode(Collections.DesignerData) 'designerData ProcessCollection(Collections.DesignerImages, False) mXMLFile.CurrentNode = oDesignerDataNode ProcessCollection(Collections.DesignerStoredImages, False) mXMLFile.CurrentNode = oDesignerDataNode ProcessCollection(Collections.DesignerText, False) End If ' Add any template data (if any nodes for the collection exist on the mailing) If mMailingCollections.ContainsKey(Collections.TemplateData) Then mXMLFile.CurrentNode = oMailPackNode mXMLFile.AddNode(Collections.Templates) ProcessCollection(Collections.TemplateData, True) End If ' Add the mailing list node mXMLFile.CurrentNode = oMailingNode Dim oMailingListNode As XmlNode = mXMLFile.AddNode(Collections.MailingList) ' Add mailing list calls If mMailingCollections.ContainsKey(Collections.MailingList) Then ProcessCollection(Collections.MailingList, False) ' Add any address data (if any nodes for the collection exist on the mailing) If mMailingCollections.ContainsKey(Collections.AddressesData) Then mXMLFile.CurrentNode = oMailingListNode mXMLFile.AddNode(Collections.Addresses) ProcessCollection(Collections.AddressesData, True) End If ' Run auto correct (fake collection to ensure run last) If mMailingCollections.ContainsKey(Collections.AutoCorrectAddresses) Then Dim oMailingListMethods As ArrayList = CType(mMailingCollections(Collections.MailingList), ArrayList) ' Temporary overwrite mailing list collection to ensure auto correct goes under mailing list, but must be after mailing list data added mMailingCollections(Collections.MailingList) = CType(mMailingCollections(Collections.AutoCorrectAddresses), ArrayList) mXMLFile.CurrentNode = oMailingListNode ProcessCollection(Collections.MailingList, False) ' Revert back collection now processed mMailingCollections(Collections.MailingList) = oMailingListMethods End If ' Add the process mailing node, completing the XML for the mailing mXMLFile.CurrentNode = oMailingNode ProcessCollection(Collections.ProcessMailing, False) Next ' Check file byte arrays are valid Dim oBytes As Byte() For Each sFileName As String In mFiles.Keys oBytes = CType(mFiles(sFileName), Byte()) If oBytes Is Nothing Then ErrorMessage = "File '" & sFileName & "' not found." mValidated = False Return False End If Next ' Validate XML schema as saves sending the data if the XML is not valid Dim oByteArray As Byte() = System.Text.Encoding.UTF8.GetBytes(Me.XMLFileString) Dim oMemoryStream As IO.MemoryStream = New IO.MemoryStream oMemoryStream.Write(oByteArray, 0, oByteArray.Length) oMemoryStream.Position = 0 oXMLTextReader = New XmlTextReader(oMemoryStream) oXMLTextReader.WhitespaceHandling = WhitespaceHandling.None Dim oXMLReaderSettings As New XmlReaderSettings() oXMLReaderSettings.Schemas.Add(XMLSchemaURL, XMLSchemaURL) oXMLReaderSettings.ValidationType = ValidationType.Schema Dim oXMLReader As XmlReader oXMLReader = XmlReader.Create(oXMLTextReader, oXMLReaderSettings) Try Do While oXMLReader.Read Loop Catch ex As Exception ErrorMessage = "Failed to validate XML file against the schema due to following failure message: " & ex.Message mValidated = False Return False Finally oXMLReader.Close() End Try ' Clear mailings and mailing collections now we have created the XML file mMailingCollections = New Hashtable mMailings = New ArrayList mValidated = False Catch ex As Exception ErrorMessage = ex.Message mValidated = False Return False End Try mValidated = True ' Set as validated so if call is before create mailing the don't need to run again Return True End Function ''' ''' Process each collection adding the method names to the XM ''' ''' ''' ''' Private Sub ProcessCollection(ByVal CollectionName As String, ByVal AddNewGroupForDuplicateMethod As Boolean) ProcessCollection(CollectionName, AddNewGroupForDuplicateMethod, False) End Sub ''' ''' Process each collection adding the method names to the XML ''' ''' ''' ''' Private Sub ProcessCollection(ByVal CollectionName As String, ByVal AddNewGroupForDuplicateMethod As Boolean, ByVal Required As Boolean) ' Get the collection of methods added for the collection Dim oMethods As ArrayList = CType(mMailingCollections(CollectionName), ArrayList) ' Check there are some methods for this collection If oMethods Is Nothing Then If Required Then Throw New Exception("To create a DocmailZip mailing you must call the " & UCase(Left(CollectionName, 1)) & Mid(CollectionName, 2, Len(CollectionName) - 1) & " routine before creating the zip file.") Else ' A unique method name collection for checking for duplicates Dim oUniqueMethodNames As New ArrayList ' Store the top parent node so can use if adding extra collection nodes Dim oParentNode As XmlNode = mXMLFile.CurrentNode ' If current node is collection do not add again (e.g. mailing list) If mXMLFile.CurrentNode.Name <> CollectionName Then mXMLFile.AddNode(CollectionName) Dim oCollectionNode As XmlNode = mXMLFile.CurrentNode Dim bLoopAddNewGroupForDuplicateMethod As Boolean Dim oLoopCollectionNode As XmlNode = Nothing Dim oTemplateData As XmlNode = Nothing ' Current template data node Dim oTemplateVariableValues As XmlNode = Nothing ' Special case for variable values Dim oMailPackVariableValues As XmlNode = Nothing ' Special case for variable values Dim oTemplateUseRules As XmlNode = Nothing ' Special case for template use rules Dim oTemplateBackgroundRules As XmlNode = Nothing ' Special case for template background rules For Each oMethodParams As MethodParams In oMethods ' Special case for variable values and rules as need to be relative to current template data node If CollectionName = Collections.TemplateData Then If (oMethodParams.MethodName = Methods.SetTemplateVariableValue OrElse oMethodParams.MethodName = Methods.SetMailPackVariableValue OrElse _ oMethodParams.MethodName = Methods.AddTemplateUseRule OrElse oMethodParams.MethodName = Methods.AddTemplateBackgroundRule) Then If oTemplateData Is Nothing Then Throw New Exception("A template must be added before template related data can be set.") mXMLFile.CurrentNode = oTemplateData Select Case oMethodParams.MethodName Case Methods.SetTemplateVariableValue If oTemplateVariableValues Is Nothing Then oTemplateVariableValues = mXMLFile.AddNode(Collections.TemplateVariableValues) oLoopCollectionNode = oTemplateVariableValues Case Methods.SetMailPackVariableValue If oMailPackVariableValues Is Nothing Then oMailPackVariableValues = mXMLFile.AddNode(Collections.MailPackVariableValues) oLoopCollectionNode = oMailPackVariableValues Case Methods.AddTemplateUseRule If oTemplateUseRules Is Nothing Then oTemplateUseRules = mXMLFile.AddNode(Collections.TemplateUseRules) oLoopCollectionNode = oTemplateUseRules Case Methods.AddTemplateBackgroundRule If oTemplateBackgroundRules Is Nothing Then oTemplateBackgroundRules = mXMLFile.AddNode(Collections.TemplateBackgroundRules) oLoopCollectionNode = oTemplateBackgroundRules End Select bLoopAddNewGroupForDuplicateMethod = False ' Ignore duplicate tags inside variable collection as can add multiple Else oTemplateData = oCollectionNode bLoopAddNewGroupForDuplicateMethod = AddNewGroupForDuplicateMethod oLoopCollectionNode = oCollectionNode End If Else bLoopAddNewGroupForDuplicateMethod = AddNewGroupForDuplicateMethod oLoopCollectionNode = oCollectionNode End If ' Check if new groupds require adding once we find a duplicate method If bLoopAddNewGroupForDuplicateMethod Then If oUniqueMethodNames.Contains(oMethodParams.MethodName) Then ' Add a new group node to the parent ' Set current node to parent above collection mXMLFile.CurrentNode = oParentNode ' Add collection node oCollectionNode = mXMLFile.AddNode(CollectionName) oLoopCollectionNode = oCollectionNode ' Reset unique collection oUniqueMethodNames = New ArrayList ' Add unique method name to the collection oUniqueMethodNames.Add(oMethodParams.MethodName) If CollectionName = Collections.TemplateData Then ' Update the template collection node oTemplateData = oLoopCollectionNode ' Reset the template variables collection so added to correct template oTemplateVariableValues = Nothing oTemplateUseRules = Nothing oTemplateBackgroundRules = Nothing End If Else ' Add unique method name to the collection oUniqueMethodNames.Add(oMethodParams.MethodName) If CollectionName = Collections.TemplateData Then ' Add all template add methods to ensure a new group is correctly added when a secondary template call is made If Not oUniqueMethodNames.Contains(Methods.AddTemplateFile) Then oUniqueMethodNames.Add(Methods.AddTemplateFile) If Not oUniqueMethodNames.Contains(Methods.AddTemplateFromLibrary) Then oUniqueMethodNames.Add(Methods.AddTemplateFromLibrary) If Not oUniqueMethodNames.Contains(Methods.AddMailPackFromLibrary) Then oUniqueMethodNames.Add(Methods.AddMailPackFromLibrary) End If End If End If ' Set the collection node as the current mode mXMLFile.CurrentNode = oLoopCollectionNode ' Add the method under the collection (unless method name is same as collection name as can be method and a collection) If oMethodParams.MethodName <> CollectionName Then mXMLFile.AddNode(oMethodParams.MethodName) ' Get the parameter names Dim oParameterNames As ArrayList = CType(mMethods(oMethodParams.MethodName), ArrayList) Dim sFileName As String = "" Dim iParamNameIndex As Integer = 0 Dim bSkip As Boolean ' Skip used to ignore byte array data ' Loop through the parameters adding the nodes to the XML file For iParam As Integer = 0 To oMethodParams.ParameterValues.Count - 1 Dim oParameterValue As Object = oMethodParams.ParameterValues(iParam) Dim sParameterValue As String bSkip = False ' Convert formats If TypeOf oParameterValue Is Boolean Then sParameterValue = LCase(CStr(oParameterValue)) ElseIf TypeOf oParameterValue Is Byte() Then ' Store the file data If Not mFiles.ContainsKey(sFileName) Then mFiles.Add(sFileName, oParameterValue) Else Dim oBytes As Byte() = CType(mFiles(sFileName), Byte()) If oBytes Is Nothing Then mFiles(sFileName) = oParameterValue End If sParameterValue = "" bSkip = True ElseIf oParameterValue Is Nothing Then sParameterValue = "" ElseIf TypeOf oParameterValue Is Date Then Dim oParameterDate As Date = CType(oParameterValue, Date) If oParameterDate = Date.MinValue Then sParameterValue = "" Else sParameterValue = oParameterDate.ToString("yyyy-MM-dd") End If ElseIf TypeOf oParameterValue Is FontName Then sParameterValue = oParameterValue.ToString.Replace("_", " ") ' Correct dash as cannot be in enum If sParameterValue = "MetaOT_Normal" Then sParameterValue = "MetaOT-Normal" If sParameterValue = "Default" Then sParameterValue = "" ElseIf TypeOf oParameterValue Is ProductType OrElse _ TypeOf oParameterValue Is ProductType OrElse _ TypeOf oParameterValue Is DeliveryType OrElse _ TypeOf oParameterValue Is AddressNameFormat OrElse _ TypeOf oParameterValue Is EnvelopeSize OrElse _ TypeOf oParameterValue Is PaymentMethod OrElse _ TypeOf oParameterValue Is DocumentType OrElse _ TypeOf oParameterValue Is AddressFontCode OrElse _ TypeOf oParameterValue Is TemplateType OrElse _ TypeOf oParameterValue Is TextJustification OrElse _ TypeOf oParameterValue Is ImageFitOption OrElse _ TypeOf oParameterValue Is DataFormat OrElse _ TypeOf oParameterValue Is CorrectionMethod OrElse _ TypeOf oParameterValue Is RuleDataFormat OrElse _ TypeOf oParameterValue Is FromEquation OrElse _ TypeOf oParameterValue Is ToEquation OrElse _ TypeOf oParameterValue Is ProofOption Then sParameterValue = oParameterValue.ToString.Replace("_", " ") If sParameterValue = "Default" Then sParameterValue = "" Else sParameterValue = CStr(oParameterValue) End If Try ' Get parameter name Dim sParameterName As String = CStr(oParameterNames(iParamNameIndex)) If Not bSkip Then ' Store file name so can add to collection when the file data is processed If sParameterName = "fileName" Then sFileName = sParameterValue If Not mFiles.ContainsKey(sFileName) Then mFiles.Add(sFileName, Nothing) End If ' Update dafaults to match XML spec If sParameterName = "copies" AndAlso sParameterValue = "0" Then sParameterValue = "1" If sParameterName = "templateInstances" AndAlso sParameterValue = "0" Then sParameterValue = "1" ' If we have a value add property to XML file If sParameterValue <> "" Then mXMLFile.AddNode(sParameterName, sParameterValue) ' Increate param name index (same except for file data) iParamNameIndex += 1 End If Catch ex As Exception iParamNameIndex = iParamNameIndex End Try Next Next End If End Sub ''' ''' Loop through complex types extracting method parameters ''' ''' ''' ''' ''' ''' Private Sub ReadComplexType(ByVal sNodeName As String, ByRef oXMLTextReader As XmlTextReader, ByVal oComplexType As ArrayList, ByVal oSimpleTypes As ArrayList) If Not mMethods.ContainsKey(sNodeName) Then mMethods.Add(sNodeName, New ArrayList()) Do While oXMLTextReader.Read AndAlso Not (oXMLTextReader.NodeType = XmlNodeType.EndElement AndAlso oXMLTextReader.Name = "xs:complexType") Dim sLoopNodeName As String = oXMLTextReader.GetAttribute("name") If oXMLTextReader.NodeType = XmlNodeType.Element AndAlso (oXMLTextReader.Name = "xs:element") Then Dim sType As String = oXMLTextReader.GetAttribute("type") Dim bParameter As Boolean = sType Is Nothing OrElse oSimpleTypes.Contains(sType) OrElse sType.StartsWith("xs:") If bParameter Then CType(mMethods(sNodeName), ArrayList).Add(sLoopNodeName) Else If Not oXMLTextReader.IsEmptyElement AndAlso oComplexType.Contains(sType) Then ReadComplexType(sType, oXMLTextReader, oComplexType, oSimpleTypes) End If End If ElseIf oXMLTextReader.Name = "xs:complexType" Then ReadComplexType(sLoopNodeName, oXMLTextReader, oComplexType, oSimpleTypes) End If Loop End Sub #End Region End Class #End Region #Region "File" Public Class File ''' ''' Open a file as a byte array ''' ''' ''' ''' Public Shared Function OpenFileAsByteArray(ByVal FilePath As String) As Byte() Dim oFileStream As System.IO.FileStream = System.IO.File.OpenRead(FilePath) Dim iBytes As Integer = CType(oFileStream.Length, Integer) Dim oByteArray(iBytes - 1) As Byte oFileStream.Read(oByteArray, 0, iBytes) oFileStream.Close() Return oByteArray End Function ''' ''' Save from byte array to file ''' ''' ''' ''' ''' Public Shared Function SaveFileFromByteArray(ByVal FileData As Byte(), ByVal FilePath As String) As Boolean If FileData Is Nothing Then Return False Else If FileData.Length = 0 Then Return False Else Dim sDirectory As String = System.IO.Path.GetDirectoryName(FilePath) If System.IO.Directory.Exists(sDirectory) Then Using oFileStream As New System.IO.FileStream(FilePath, System.IO.FileMode.Create) oFileStream.Write(FileData, 0, FileData.Length) oFileStream.Close() End Using Return True Else Return False End If End If End If End Function End Class #End Region #Region "XML" ''' ''' Wrapper class for XML file creation ''' ''' Public Class XMLFile Public XMLDocument As System.Xml.XmlDocument Public RootNode As System.Xml.XmlNode Public CurrentNode As System.Xml.XmlNode Public CurrentNameSpace As String Public Sub New() XMLDocument = New System.Xml.XmlDocument ' Declaration Dim oXMLDeclaration As System.Xml.XmlDeclaration = XMLDocument.CreateXmlDeclaration("1.0", "utf-8", Nothing) XMLDocument.InsertBefore(oXMLDeclaration, XMLDocument.DocumentElement) End Sub ''' ''' Add a root node setting the root node and current node to the newly created node. ''' ''' ''' ''' ''' ''' Public Function AddRootNode(ByVal NodeName As String, ByVal XMLNameSpace As String, ByVal XSISchemaLocation As String) As System.Xml.XmlNode ' Root element RootNode = XMLDocument.CreateElement(NodeName, XMLNameSpace) ' Set the current namespace Me.CurrentNameSpace = XMLNameSpace Dim oAttributeXSINamespace As System.Xml.XmlAttribute = XMLDocument.CreateAttribute("xmlns", "xsi", "http://www.w3.org/2000/xmlns/") oAttributeXSINamespace.Value = "http://www.w3.org/2001/XMLSchema-instance" RootNode.Attributes.Append(oAttributeXSINamespace) Dim oAttributeXSISchemaLocation = XMLDocument.CreateAttribute("xsi", "schemaLocation", "http://www.w3.org/2001/XMLSchema-instance") oAttributeXSISchemaLocation.Value = XSISchemaLocation RootNode.Attributes.Append(oAttributeXSISchemaLocation) XMLDocument.AppendChild(RootNode) CurrentNode = RootNode Return RootNode End Function ''' ''' Add a node setting the current node to the newly added node. ''' ''' ''' ''' Public Function AddNode(ByVal NodeName As String) As System.Xml.XmlNode Dim oXMLData As System.Xml.XmlNode = XMLDocument.CreateElement(NodeName, Me.CurrentNameSpace) CurrentNode.AppendChild(oXMLData) CurrentNode = oXMLData Return oXMLData End Function ''' ''' Add a node and value as a child of the current node. ''' ''' ''' ''' ''' Public Function AddNode(ByVal NodeName As String, ByVal NodeValue As String) As System.Xml.XmlNode Dim oXMLData As System.Xml.XmlNode = XMLDocument.CreateElement(NodeName, Me.CurrentNameSpace) Dim oXMLTextKey As System.Xml.XmlText = XMLDocument.CreateTextNode(NodeValue) oXMLData.AppendChild(oXMLTextKey) CurrentNode.AppendChild(oXMLData) Return oXMLData End Function End Class #End Region #Region "Zip" Public Class Zip Inherits CollectionBase Public Function Add(ByVal sFilename As String, ByVal oBuffer As Byte()) As ZipFile Dim oFileToZip As New ZipFile(sFilename, oBuffer) Me.InnerList.Add(oFileToZip) Return oFileToZip End Function Public Sub AddFolder(ByVal FolderPath As String) Dim myDirectory As DirectoryInfo myDirectory = New DirectoryInfo(FolderPath) WorkWithDirectory(myDirectory, FolderPath) End Sub Private Sub WorkWithDirectory(ByVal aDir As DirectoryInfo, ByVal OuterFolder As String) Dim nextDir As DirectoryInfo WorkWithFilesInDir(aDir, OuterFolder) For Each nextDir In aDir.GetDirectories WorkWithDirectory(nextDir, OuterFolder) Next End Sub Private Sub WorkWithFilesInDir(ByVal aDir As DirectoryInfo, ByVal OuterFolder As String) Dim aFile As FileInfo For Each aFile In aDir.GetFiles() Dim sFile As String = Right(aFile.FullName, aFile.FullName.Length - OuterFolder.Length - 1) Me.Add(sFile, File.OpenFileAsByteArray(aFile.FullName)) Next End Sub Default Public ReadOnly Property Item(ByVal iIndex As Integer) As ZipFile Get Return CType(Me.InnerList.Item(iIndex), ZipFile) End Get End Property Public Sub Remove(ByVal oBuffer As ZipFile) Me.InnerList.Remove(oBuffer) End Sub Public ReadOnly Property ToZip() As Byte() Get If Count = 0 Then Return Nothing Dim oMemStream As New MemoryStream() Dim oZipStream As New ZipOutputStream(oMemStream) Dim oZipEntry As ZipEntry Dim oCrc As New Crc32() Dim i As Integer Try oZipStream.SetLevel(9) For i = 0 To Count - 1 oZipEntry = New ZipEntry(Me(i).Filename) With oZipEntry .DateTime = Now .Size = Me(i).Data.Length oCrc.Reset() oCrc.Update(Me(i).Data) '.Crc = oCrc.Value Remove this line as causes problems in some zip applications End With With oZipStream .PutNextEntry(oZipEntry) .Write(Me(i).Data, 0, Me(i).Data.Length) End With Next i With oZipStream .Finish() .Close() End With Return oMemStream.ToArray Finally If Not oZipStream.IsFinished Then oZipStream.Close() oZipStream = Nothing End Try End Get End Property Public Sub Extract(ByVal ZipFile As String, ByVal SaveToFolder As String, ByVal Password As String, ByVal DeleteZipFile As Boolean) Dim s As ZipInputStream = New ZipInputStream(System.IO.File.OpenRead(ZipFile)) If (Password <> "") Then s.Password = Password Dim theEntry As ZipEntry Dim tmpEntry As String = String.Empty theEntry = s.GetNextEntry() While Not theEntry Is Nothing Dim directoryName As String = SaveToFolder Dim fileName As String = Path.GetFileName(theEntry.Name) ' create directory If directoryName <> "" Then Directory.CreateDirectory(directoryName) End If If fileName <> String.Empty Then 'If theEntry.Name.IndexOf(".ini") < 0 Then Dim fullPath As String = directoryName + "\\" + theEntry.Name fullPath = fullPath.Replace("\\ ", "\\") Dim fullDirPath As String = Path.GetDirectoryName(fullPath) If Not Directory.Exists(fullDirPath) Then Directory.CreateDirectory(fullDirPath) Dim streamWriter As FileStream = System.IO.File.Create(fullPath) Dim size As Integer = 2048 Dim data(2048) As Byte While (True) size = s.Read(data, 0, data.Length) If (size > 0) Then streamWriter.Write(data, 0, size) Else Exit While End If End While streamWriter.Close() 'End If End If theEntry = s.GetNextEntry() End While s.Close() If (DeleteZipFile) AndAlso System.IO.File.Exists(ZipFile) Then System.IO.File.Delete(ZipFile) End Sub End Class Public Class ZipFile Private _Filename As String Private _Data As Byte() Public Property Filename() As String Get Return _Filename End Get Set(ByVal Value As String) _Filename = Value End Set End Property Public Property Data() As Byte() Get Return _Data End Get Set(ByVal Value As Byte()) _Data = Value End Set End Property Sub New(ByVal sFilename As String, ByVal oData As Byte()) _Filename = sFilename _Data = oData End Sub End Class #End Region #Region "Web service" ''' ''' Helper class for using the web service ''' ''' Public Class WebService #Region "Constants" Public Const LiveSchemaURL As String = "https://www.cfhdocmail.com/LiveAPI2/DMWS.xsd" Public Class Statuses Public Const ErrorInProcessing As String = "Error in processing" Public Const AwaitingSubmittingForProcessing As String = "Awaiting submitting for processing" Public Const PartialProcessingComplete As String = "Partial processing complete" Public Const ProcessingMailingList As String = "Processing mailing list" Public Const MailingListProcessed As String = "Mailing list processed" Public Const AwaitingProcessing As String = "Awaiting processing" Public Const ProcessingMailingGeneratingDesignerTemplate As String = "Processing mailing - generating designer template" Public Const ProcessingMailingImportingTemplates As String = "Processing mailing - importing templates" Public Const ProcessingMailingImportingAddresses As String = "Processing mailing - importing addresses" Public Const ProcessingMailingValidatingAddresses As String = "Processing mailing - validating addresses" Public Const ProcessingMailingGeneratingProof As String = "Processing mailing - generating proof" Public Const ProcessingMailingApprovingMailing As String = "Processing mailing - approving mailing" Public Const MailingSubmitted As String = "Mailing submitted" Public Const MailingProcessed As String = "Mailing processed" End Class Public Class ExtendedCallMethods Public Const AddCampaign As String = "AddCampaign" Public Const AddLibraryTemplateUseRule As String = "AddLibraryTemplateUseRule" Public Const AddLibraryTemplateBackgroundRule As String = "AddLibraryTemplateBackgroundRule" Public Const AddMailingListFileWithPassword As String = "AddMailingListFileWithPassword" Public Const AddMailingListFileWithPasswordToLibrary As String = "AddMailingListFileWithPasswordToLibrary" Public Const AgreeToTerms As String = "AgreeToTerms" Public Const CanUseDotpost As String = "CanUseDotpost" Public Const ContentApproveMailing As String = "ContentApproveMailing" Public Const CreateZipMailing As String = "CreateZipMailing" Public Const DeleteAddress As String = "DeleteAddress" Public Const DeleteLibraryBackground As String = "DeleteLibraryBackground" Public Const DeleteLibraryMailPack As String = "DeleteLibraryMailPack" Public Const DeleteLibraryTemplate As String = "DeleteLibraryTemplate" Public Const DeleteLibraryTemplateFromLibraryMailPack As String = "DeleteLibraryTemplateFromLibraryMailPack" Public Const GetClosedFaceEnvelopesImage As String = "GetClosedFaceEnvelopesImage" Public Const GetDefaultMailingOptions As String = "GetDefaultMailingOptions" Public Const GetMailingFile As String = "GetMailingFile" Public Const GetLibraryBackgroundFile As String = "GetLibraryBackgroundFile" Public Const GetLibraryMailPackFile As String = "GetLibraryMailPackFile" Public Const GetLibraryTemplateFile As String = "GetLibraryTemplateFile" Public Const GetPriceEstimateWithReturns As String = "GetPriceEstimateWithReturns" Public Const GetProcessingError As String = "GetProcessingError" Public Const GetProofPackFile As String = "GetProofPackFile" Public Const GetProofPackImage As String = "GetProofPackImage" Public Const GetReturnAddresses As String = "GetReturnAddresses" Public Const GetUserLoginKey As String = "GetUserLoginKey" Public Const GetZipStatus As String = "GetZipStatus" Public Const ListClosedFaceEnvelopes As String = "ListClosedFaceEnvelopes" Public Const ListDotpostCampaigns As String = "ListDotpostCampaigns" Public Const ListMailingProcessingData As String = "ListMailingProcessingData" Public Const ListMailingsWithDescription As String = "ListMailingsWithDescription" Public Const ListOrganisationStructureData As String = "ListOrganisationStructureData" Public Const ListProofPackDetails As String = "ListProofPackDetails" Public Const ListReplyEnvelopes As String = "ListReplyEnvelopes" Public Const ListReturns As String = "ListReturns" Public Const PayMailing As String = "PayMailing" Public Const RefreshBudgetPeriods As String = "RefreshBudgetPeriods" Public Const SetDataIntelligence As String = "SetDataIntelligence" Public Const SetDataIntelligenceDefaultTemplateRule As String = "SetDataIntelligenceDefaultTemplateRule" Public Const SetMailingAPICancelOnly As String = "SetMailingAPICancelOnly" Public Const SetMailingReturnsManaged As String = "SetMailingReturnsManaged" Public Const SetTemplateBackground As String = "SetTemplateBackground" Public Const TermsAgreementRequired As String = "TermsAgreementRequired" Public Const UpdateLibraryBackground As String = "UpdateLibraryBackground" Public Const UpdateLibraryTemplate As String = "UpdateLibraryTemplate" End Class #End Region #Region "Return Format" Public Class ReturnFormat #Region "Constants" Public Const JavaScript As String = "JavaScript" Public Const JSON As String = "JSON" Public Const Text As String = "Text" Public Const XML As String = "XML" #End Region #Region "Properties" Private mReturnHash As Hashtable Private KeyToLowerCase As Boolean ''' ''' The raw data returned, it is recommended to use GetHashValue to pass the returned data. ''' ''' ''' ''' Public Property ReturnHash() As Hashtable Get ReturnHash = mReturnHash End Get Set(ByVal value As Hashtable) mReturnHash = value End Set End Property ''' ''' Does the return data contain an error? ''' ''' ''' ''' Public ReadOnly Property HasError() As Boolean Get Return Me.GetHashValue("Error code") <> "" End Get End Property ''' ''' Return error code ''' ''' ''' ''' Public ReadOnly Property ErrorCode() As Integer Get Return CInt(Me.GetHashValue("Error code")) End Get End Property ''' ''' Return error code string ''' ''' ''' ''' Public ReadOnly Property ErrorCodeString() As String Get Return Me.GetHashValue("Error code string") End Get End Property ''' ''' Return error message ''' ''' ''' ''' Public ReadOnly Property ErrorMessage() As String Get Return Me.GetHashValue("Error message") End Get End Property ''' ''' Retun return data from a list call ''' ''' ''' ''' Public ReadOnly Property ListData() As String Get Return Me.GetHashValue("List") End Get End Property #End Region #Region "New construct" ''' ''' Create a new return format object for managing return data in text format ''' ''' ''' Public Sub New(ByVal ReturnString As String) SetReturn(ReturnString, False) End Sub ''' ''' Create a new return format object for managing return data in text format. ''' ''' ''' ''' Public Sub New(ByVal ReturnString As String, ByVal KeyToLowerCase As Boolean) SetReturn(ReturnString, KeyToLowerCase) End Sub ''' ''' Create a new return format object for managing return data in text format. ''' If ListReturn is true then the ListData property wil be populated if the call is successful. ''' ''' ''' ''' Public Sub New(ByVal ReturnString As String, ByVal KeyToLowerCase As Boolean, ByVal ListReturn As Boolean) SetReturn(ReturnString, KeyToLowerCase, ListReturn) End Sub ''' ''' Update the return string to manage a new set of return data in text format ''' ''' ''' Public Sub SetReturn(ByVal ReturnString As String) SetReturn(ReturnString, False, False) End Sub ''' ''' Update the return string to manage a new set of return data in text format ''' ''' ''' Public Sub SetReturn(ByVal ReturnString As String, ByVal KeyToLowerCase As Boolean) SetReturn(ReturnString, KeyToLowerCase, False) End Sub ''' ''' Update the return string to manage a new set of return data in text format ''' ''' ''' Public Sub SetReturn(ByVal ReturnString As String, ByVal KeyToLowerCase As Boolean, ByVal ListReturn As Boolean) Me.KeyToLowerCase = KeyToLowerCase Me.ReturnHash = ReturnFormat.ToHashTable(ReturnString, KeyToLowerCase, ListReturn) End Sub ''' ''' Get hash value using a key. ''' If KeyToLowerCase was passed as True to the New construct or to SetReturn, then the hash key match will be case insensitive. ''' ''' ''' ''' Public Function GetHashValue(ByVal Key As String) As String If Key Is Nothing OrElse Me.ReturnHash Is Nothing Then Return "" If Me.KeyToLowerCase Then Key = Key.ToLower Dim sValue As String = CType(Me.ReturnHash(Key), String) If sValue Is Nothing Then sValue = "" Return sValue End Function #End Region #Region "Shared functions" ''' ''' Convert the text formatted result into a hash table for easy reference ''' ''' ''' ''' Public Shared Function ToHashTable(ByVal ResultData As String) As Hashtable Return ToHashTable(ResultData, False, False) End Function ''' ''' Convert the text formatted result into a hash table for easy reference. ''' If ListReturn is true then the return hash will contain a 'List' property containing the CSV string if the call is succesful. ''' ''' ''' ''' Public Shared Function ToHashTable(ByVal ResultData As String, ByVal KeyToLowerCase As Boolean, ByVal ListReturn As Boolean) As Hashtable Dim oHashTable As New Hashtable Dim bErrorMessage As Boolean = False Dim sKey As String Dim sData As String Dim iIndex As Integer If ListReturn AndAlso Not ResultData.ToLower.StartsWith("error") Then sKey = "List" If KeyToLowerCase Then sKey = sKey.ToLower oHashTable.Add(sKey, ResultData) Else If Not ResultData = "" Then For Each sLine As String In ResultData.Split(vbCrLf.ToCharArray) If sLine <> "" Then If bErrorMessage Then sKey = "Error message" If KeyToLowerCase Then sKey = sKey.ToLower oHashTable(sKey) = CType(oHashTable(sKey), String) & vbCrLf & sLine Else iIndex = sLine.IndexOf(": ") sKey = sLine.Substring(0, iIndex) If KeyToLowerCase Then sKey = sKey.ToLower sData = sLine.Substring(iIndex + 2, sLine.Length - iIndex - 2) If (KeyToLowerCase AndAlso sKey = "error message") OrElse (Not KeyToLowerCase AndAlso sKey = "Error message") Then bErrorMessage = True oHashTable.Add(sKey, sData) End If End If Next End If End If Return oHashTable End Function #End Region End Class #End Region End Class #End Region