2914 W 29th - sewer and water locations.docm
This report is generated from a file or URL submitted to this webservice on February 9th 2017 16:22:55 (UTC) and action script Heavy Anti-Evasion
Guest System: Windows 7 32 bit, Home Premium, 6.1 (build 7601), Service Pack 1, Office 2010 v14.0.4
Report generated by
Falcon Sandbox v6.10 © Hybrid Analysis
Incident Response
Risk Assessment
- Fingerprint
-
Reads the active computer name
Reads the cryptographic machine GUID - Spreading
- Opens the MountPointManager (often used to detect additional infection locations)
Indicators
Not all malicious and suspicious indicators are displayed. Get your own cloud service or the full version to view all details.
-
Malicious Indicators 3
-
External Systems
-
Sample was identified as malicious by a trusted Antivirus engine
- details
- No specific details available
- source
- External System
- relevance
- 5/10
-
Sample was identified as malicious by at least one Antivirus engine
- details
- 5/56 Antivirus vendors marked sample as malicious (8% detection rate)
- source
- External System
- relevance
- 8/10
-
Sample was identified as malicious by a trusted Antivirus engine
-
Unusual Characteristics
-
Contains embedded VBA macros with keywords that indicate auto-execute behavior
- details
-
Found keyword "AutoClose" which indicates: "Runs when the Word document is closed"
Found keyword "AutoOpen" which indicates: "Runs when the Word document is opened" - source
- Static Parser
- relevance
- 10/10
-
Contains embedded VBA macros with keywords that indicate auto-execute behavior
-
Suspicious Indicators 3
-
Exploit/Shellcode
-
Found URL in decoded VBA string
- details
-
Heuristic match: "control.id"
Pattern match: "http://Motobit.cz"
Heuristic match: "dataTable.id"
Heuristic match: "tableRow.Parent.id" - source
- File/Memory
- relevance
- 10/10
-
Found URL in decoded VBA string
-
Unusual Characteristics
-
Contains embedded VBA macros with interesting strings
- details
- Found pattern type "Executable file name" with value: "Word.Application"
- source
- Static Parser
- relevance
- 10/10
-
Contains embedded VBA macros with suspicious keywords
- details
-
Found suspicious keyword "Windows" which indicates: "May enumerate application windows (if combined with Shell.Application object)"
Found suspicious keyword "Chr" which indicates: "May attempt to obfuscate specific strings"
Found suspicious keyword "Lib" which indicates: "May run code from a DLL"
Found suspicious keyword "Binary" which indicates: "May read or write a binary file (if combined with Open)"
Found suspicious keyword "Write" which indicates: "May write to a file (if combined with Open)"
Found suspicious keyword "Kill" which indicates: "May delete a file"
Found suspicious keyword "Open" which indicates: "May open a file"
Found suspicious keyword "SaveToFile" which indicates: "May create a text file"
Found suspicious keyword "SendKeys" which indicates: "May control another application by simulating user keystrokes"
Found suspicious keyword "sample" which indicates: "May detect Anubis Sandbox" - source
- Static Parser
- relevance
- 10/10
-
Contains embedded VBA macros with interesting strings
-
Informative 17
-
Environment Awareness
-
Reads the active computer name
- details
- "WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\COMPUTERNAME\ACTIVECOMPUTERNAME"; Key: "COMPUTERNAME")
- source
- Registry Access
- relevance
- 5/10
-
Reads the cryptographic machine GUID
- details
- "WINWORD.EXE" (Path: "HKLM\SOFTWARE\MICROSOFT\CRYPTOGRAPHY"; Key: "MACHINEGUID")
- source
- Registry Access
- relevance
- 10/10
-
Reads the active computer name
-
General
-
Contains embedded VBA macros
- details
-
File "ThisDocument.cls" (Streampath: "VBA/ThisDocument") has code: ""
File "PosseWordInterface.bas" (Streampath: "VBA/PosseWordInterface") has code: "Option Explicit
'=================================================================
'2013-07-30, Completely restructured to use REST services and DOCM format
'2012-02-08, Compatible with Word 2010
'2011-11-08, Now removes all watermarks when doc is signed by a user
'2011-04-12, Fixed a browser issue with Chrome which adds spaces between the doc name and the count "name (2)"
'2011-01-20, Issue 1163, AVO, Consolidated from various branches.
' Shared variables.
Type DocProps
PosseAdditionalDataFieldPrefix As String
PosseAutoGetData As Boolean
PosseAutoSaveOnOpen As Boolean
PosseBaseURI As String
PosseDataSourceId As String
PosseDocumentObjectId As String
PosseGetAdditionalDataShow As Boolean
PosseGetDataShow As Boolean
PosseGetRecipientsShow As Boolean
PosseIncludeUnsigned As Boolean
PosseRecipientRecordset As String
PosseRecordset As String
PosseSaveAsPDF As Boolean
PosseSaveDocumentShow As Boolean
PosseSendCredentials As Boolean
PosseSessionToken As String
PosseSignDocumentShow As Boolean
PosseSignIsCompleteOnDocument As Boolean
PosseSignIsCompleteOnSource As Boolean
PosseSaveAsRevisionShow As Boolean
End Type
Dim Props As DocProps
Type AuthProps
UserId As String
Password As String
AuthString As String
End Type
Dim Auth As AuthProps
Dim Images As Scripting.Dictionary
Dim CredentialsOK As Boolean
Dim FileHasUniqueName As Boolean
Dim UnsignedDocument() As Byte
Dim Ajax As New MSXML2.XMLHTTP60
Const ERR_MEMBER_NOT_FOUND = 5941 ' The requested member of the collection does not exist.
Const MAX_PATH = 260
#If VBA7 Then
Private Declare PtrSafe Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As LongPtr, ByVal lpBuffer As String) As Long
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
#Else
Private Declare Function GetTempPath Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
#End If
' Force Close->Save to save back to Posse
Sub AutoClose()
If ActiveDocument.Saved Then
ActiveWindow.Close
Else
Select Case MsgBox("Do you want to save changes you made to """ & ThisDocument.Name & """?", vbExclamation + vbYesNoCancel + vbDefaultButton1)
Case vbYes
Dim result As Long
result = saveDocument("", False)
ActiveWindow.Close
Case vbNo
ActiveDocument.Saved = True
ActiveWindow.Close
Case vbCancel
SendKeys "{ESC}"
End Select
End If
End Sub
' To open the template macro document without running this Macro, you can use
' the /m switch or hold the shift key down. Otherwise, you lose your custom props.
Public Sub AutoOpen()
If PosseWordMerge.PosseWordInterface.LoadProperties And Props.PosseGetDataShow Then
If getData("") = 1 And Props.PosseSaveDocumentShow And Props.PosseAutoSaveOnOpen Then
Call saveDocument
End If
End If
End Sub
' Load the document properties into a container, and delete the properties so that once the document has
' been closed, it will not be active if it is reopened in Word without re-downloading. Return
' the value of the AutoGetData property
Public Function LoadProperties() As Boolean
On Error GoTo errorHandler:
LoadProperties = False
Props.PosseAdditionalDataFieldPrefix = Trim(ActiveDocument.CustomDocumentProperties("PosseAdditionalDataFieldPrefix").Value)
ActiveDocument.CustomDocumentProperties("PosseAdditionalDataFieldPrefix").Delete
Props.PosseAutoGetData = Trim(ActiveDocument.CustomDocumentProperties("PosseAutoGetData").Value)
ActiveDocument.CustomDocumentProperties("PosseAutoGetData").Delete
Props.PosseAutoSaveOnOpen = Trim(ActiveDocument.CustomDocumentProperties("PosseAutoSaveOnOpen").Value)
ActiveDocument.CustomDocumentProperties("PosseAutoSaveOnOpen").Delete
Props.PosseBaseURI = Trim(ActiveDocument.CustomDocumentProperties("PosseBaseURI").Value)
ActiveDocument.CustomDocumentProperties("PosseBaseURI").Delete
Props.PosseDataSourceId = Trim(ActiveDocument.CustomDocumentProperties("PosseDataSourceId").Value)
ActiveDocument.CustomDocumentProperties("PosseDataSourceId").Delete
Props.PosseDocumentObjectId = Trim(ActiveDocument.CustomDocumentProperties("ObjectId").Value)
ActiveDocument.CustomDocumentProperties("ObjectId").Delete
Props.PosseGetAdditionalDataShow = Trim(ActiveDocument.CustomDocumentProperties("PosseGetAdditionalDataShow").Value)
ActiveDocument.CustomDocumentProperties("PosseGetAdditionalDataShow").Delete
Props.PosseGetDataShow = Trim(ActiveDocument.CustomDocumentProperties("PosseGetDataShow").Value)
ActiveDocument.CustomDocumentProperties("PosseGetDataShow").Delete
Props.PosseGetRecipientsShow = Trim(ActiveDocument.CustomDocumentProperties("PosseGetRecipientsShow").Value)
ActiveDocument.CustomDocumentProperties("PosseGetRecipientsShow").Delete
Props.PosseIncludeUnsigned = Trim(ActiveDocument.CustomDocumentProperties("PosseIncludeUnsigned").Value)
ActiveDocument.CustomDocumentProperties("PosseIncludeUnsigned").Delete
Props.PosseRecipientRecordset = Trim(ActiveDocument.CustomDocumentProperties("PosseRecipientRecordset").Value)
ActiveDocument.CustomDocumentProperties("PosseRecipientRecordset").Delete
Props.PosseRecordset = Trim(ActiveDocument.CustomDocumentProperties("PosseRecordset").Value)
ActiveDocument.CustomDocumentProperties("PosseRecordset").Delete
Props.PosseSaveAsPDF = Trim(ActiveDocument.CustomDocumentProperties("PosseSaveAsPDF").Value)
ActiveDocument.CustomDocumentProperties("PosseSaveAsPDF").Delete
Props.PosseSaveDocumentShow = Trim(ActiveDocument.CustomDocumentProperties("PosseSaveDocumentShow").Value)
ActiveDocument.CustomDocumentProperties("PosseSaveDocumentShow").Delete
Props.PosseSendCredentials = ActiveDocument.CustomDocumentProperties("PosseSendCredentials").Value
ActiveDocument.CustomDocumentProperties("PosseSendCredentials").Delete
Props.PosseSessionToken = Trim(ActiveDocument.CustomDocumentProperties("PosseSessionToken").Value)
ActiveDocument.CustomDocumentProperties("PosseSessionToken").Delete
Props.PosseSignDocumentShow = Trim(ActiveDocument.CustomDocumentProperties("PosseSignDocumentShow").Value)
ActiveDocument.CustomDocumentProperties("PosseSignDocumentShow").Delete
Props.PosseSignIsCompleteOnDocument = Trim(ActiveDocument.CustomDocumentProperties("PosseSignIsCompleteOnDocument").Value)
ActiveDocument.CustomDocumentProperties("PosseSignIsCompleteOnDocument").Delete
Props.PosseSignIsCompleteOnSource = Trim(ActiveDocument.CustomDocumentProperties("PosseSignIsCompleteOnSource").Value)
ActiveDocument.CustomDocumentProperties("PosseSignIsCompleteOnSource").Delete
Props.PosseSaveAsRevisionShow = Trim(ActiveDocument.CustomDocumentProperties("PosseSaveAsRevisionShow").Value)
ActiveDocument.CustomDocumentProperties("PosseSaveAsRevisionShow").Delete
LoadProperties = Props.PosseAutoGetData
errorHandler:
End Function
' Get current trace key
Private Function getTraceKey() As String
On Error GoTo errorHandler:
getTraceKey = Trim(ActiveDocument.CustomDocumentProperties("PosseTraceKey").Value)
Exit Function
errorHandler:
getTraceKey = ""
End Function
Sub showButton(control As IRibbonControl, ByRef visible)
If control.id = "CallGetData_1_1CA78EEC" Then
visible = Props.PosseGetDataShow
ElseIf control.id = "CallGetData_2_1CA78EEC" Then
visible = Props.PosseGetAdditionalDataShow
ElseIf control.id = "CallRecipient_3_1CA78EEC" Then
visible = Props.PosseGetRecipientsShow
ElseIf control.id = "CallSaveDocument_4_1CA78EEC" Then
visible = Props.PosseSaveDocumentShow
ElseIf control.id = "CallSignDocument_5_1CA78EEC" Then
visible = Not Props.PosseSaveAsPDF
ElseIf control.id = "CallSignDocument_6_1CA78EEC" Then
visible = Props.PosseSaveAsPDF
ElseIf control.id = "CallSaveRevision_7_1CA78EEC" Then
visible = False
Else
visible = True
End If
End Sub
Public Sub CallGetData(IControl As IRibbonControl)
'Call AutoOpen
Dim result As Long
result = getData("")
End Sub
Public Sub CallGetAdditionalData(IControl As IRibbonControl)
Dim result As Long
result = getData(Props.PosseAdditionalDataFieldPrefix)
End Sub
Public Sub CallGetRecipients(IControl As IRibbonControl)
Dim result As Long
result = getData("Recipients")
End Sub
Public Sub CallSaveDocument(IControl As IRibbonControl)
Dim result As Long
result = saveDocument("", False)
End Sub
Public Sub CallSignDocument(IControl As IRibbonControl)
Call signDocument
End Sub
Public Sub CallSaveRevision(IControl As IRibbonControl)
Dim result As Long
result = saveDocument("", False, True)
End Sub
Sub FileSave()
'
' FileSave Macro
' Saves the active document or template
'
Dim result As Long
result = saveDocument("", False)
End Sub
' Overriding FileSaveAs does not work in Word 2013.
Sub FileSaveAs()
With Dialogs(wdDialogFileSaveAs)
.Format = 12
If .Display = 0 Then Exit Sub
If .Format = 12 Then
.Execute
Else
MsgBox ("You are only allowed to save in docx format. Please try again.")
Call FileSaveAs
End If
End With
End Sub
' For the life of me, I can't find a better way to determine if a dynamic array is uninitialized...
Private Function arrayIsInitialized(a As Variant)
On Error GoTo errorHandler:
If UBound(a) <> 0 Then
arrayIsInitialized = True
End If
Exit Function
errorHandler:
arrayIsInitialized = False
End Function
' Perform a base 64 decode on the provided value.
Private Function base64Decode(ByVal base64String)
'1999 Antonin Foller, Motobit Software, http://Motobit.cz
Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
Dim dataLength, sOut, groupBegin
'remove white spaces, If any
base64String = Replace(base64String, vbCrLf, "")
base64String = Replace(base64String, vbTab, "")
base64String = Replace(base64String, " ", "")
'The source must consists from groups with Len of 4 chars
dataLength = Len(base64String)
If dataLength Mod 4 <> 0 Then
Err.Raise 1, "Base64Decode", "Bad Base64 string."
Exit Function
End If
' Now decode each group:
For groupBegin = 1 To dataLength Step 4
Dim numDataBytes, charCounter, thisChar, thisData, nGroup, pOut
' Each data group encodes up To 3 actual bytes.
numDataBytes = 3
nGroup = 0
For charCounter = 0 To 3
' Convert each character into 6 bits of data, And add it To
' an integer For temporary storage. If a character is a '=', there
' is one fewer data byte. (There can only be a maximum of 2 '=' In
' the whole string.)
thisChar = Mid(base64String, groupBegin + charCounter, 1)
If thisChar = "=" Then
numDataBytes = numDataBytes - 1
thisData = 0
Else
thisData = InStr(1, Base64, thisChar, vbBinaryCompare) - 1
End If
If thisData = -1 Then
Err.Raise 2, "Base64Decode", "Bad character In Base64 string."
Exit Function
End If
nGroup = 64 * nGroup + thisData
Next
'Hex splits the long To 6 groups with 4 bits
nGroup = Hex(nGroup)
'Add leading zeros
nGroup = String(6 - Len(nGroup), "0") & nGroup
'Convert the 3 byte hex integer (6 chars) To 3 characters
pOut = Chr(CByte("&H" & Mid(nGroup, 1, 2))) + _
Chr(CByte("&H" & Mid(nGroup, 3, 2))) + _
Chr(CByte("&H" & Mid(nGroup, 5, 2)))
'add numDataBytes characters To out string
sOut = sOut & Left(pOut, numDataBytes)
Next
base64Decode = StrConv(sOut, vbFromUnicode)
End Function
Private Function checkRecordsets(recordsets As Scripting.Dictionary, formFieldName As String) As Boolean
If recordsets.count = 0 Then
checkRecordsets = False
ElseIf recordsets.Exists(Left(formFieldName, InStrRev(formFieldName, ".") - 1)) Then
checkRecordsets = recordsets.Item(Left(formFieldName, InStrRev(formFieldName, ".") - 1)).count > 0
Else
checkRecordsets = False
End If
End Function
' Check if the given field name should be processed.
Private Function checkPrefix(fieldPrefix As String, ByRef formFieldName)
Dim ok As Boolean
ok = True
' Check for a prefix.
If Len(fieldPrefix) = 0 Then
If Left(formFieldName, 1) = "[" Then
ok = False
End If
ElseIf LCase(Left(formFieldName, Len(fieldPrefix) + 2)) = "[" & LCase(fieldPrefix) & "]" Then
formFieldName = Mid(formFieldName, InStr(formFieldName, "]") + 1)
Else
ok = False
End If
checkPrefix = ok
End Function
' Clear everything out of the clipboard
Private Sub clearClipBoard()
Dim oData As New DataObject
On Error Resume Next
oData.SetText text:="" ' Store nothing in the object
oData.PutInClipboard ' empty the clipboard
Selection.HomeKey ' Go to top of document (wdStory)
End Sub
' Delete temporary image data files.
Private Function deleteImageFiles()
Dim imageFile
For Each imageFile In Images.Items
Kill imageFile
Next
Set Images = Nothing
End Function
Private Function formatErrorDescription(Optional additionalMessage As String = "")
If (Len(additionalMessage) > 0) Then
Select Case (Right$(additionalMessage, 1))
Case ".", "!", "?"
additionalMessage = additionalMessage + vbCrLf
Case "
"
additionalMessage = additionalMessage + " "
Case Else
additionalMessage = additionalMessage + "
"
End Select
End If
formatErrorDescription = additionalMessage + Err.Description + " (" & Err.Number & ")"
End Function
Private Sub showError(functionName As String, Optional additionalMessage As String = "")
MsgBox formatErrorDescription(additionalMessage) + vbCrLf + vbCrLf + "Source: " + Err.Source + "." + functionName + "()", vbCritical
End Sub
' Format Document
Private Sub formatDocument()
On Error GoTo errorHandler:
' Format document body
With Selection.Find
.ClearFormatting
.Replacement.ClearFormatting
End With
Selection.WholeStory
With Selection.Find
.text = ""
.MatchWildcards = False
.Replacement.text = ""
.ClearFormatting
.Replacement.ClearFormatting
End With
SS_FormatDocument
Selection.WholeStory
' Apply Character Styles second
With Selection.Find
.ClearFormatting
.Replacement.text = "\1"
.Forward = True
.Wrap = False
.Format = True
.MatchCase = False
.MatchWholeWord = False
.MatchAllWordForms = False
.MatchSoundsLike = False
.MatchWildcards = True
.Replacement.ClearFormatting
End With
' Replace with boldface
Selection.Find.text = "\<b\>(*)\</b\>"
Selection.Find.Replacement.Font.Bold = True
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Replacement.Font.Bold = False
' Replace with italics
Selection.Find.text = "\<i\>(*)\</i\>"
Selection.Find.Replacement.Font.Italic = True
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Replacement.Font.Italic = False
' Replace with underline
Selection.Find.text = "\<u\>(*)\</u\>"
Selection.Find.Replacement.Font.Underline = wdUnderlineSingle
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.Replacement.Font.Underline = wdUnderlineNone
' Replace superscript
Selection.Find.text = "\<sup\>(*)\</sup\>"
Selection.Find.Replacement.Font.Superscript = True
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Replacement.Font.Superscript = False
' Replace subscript
Selection.Find.text = "\<sub\>(*)\</sub\>"
Selection.Find.Replacement.Font.Subscript = True
Selection.Find.Execute Replace:=wdReplaceAll
Selection.Find.ClearFormatting
Selection.Find.Replacement.Font.Subscript = False
' Replace with paragraph break
Selection.Find.text = "\<br /\>"
Selection.Find.Replacement.text = "^p"
Selection.Find.Execute Replace:=wdReplaceAll
' Replace with manual line break
Selection.Find.text = "\<lbr /\>"
Selection.Find.Replacement.text = "^l"
Selection.Find.Execute Replace:=wdReplaceAll
' Replace with bullet point
Selection.Find.text = "&bull;"
Selection.Find.Replacement.text = "\x95"
Selection.Find.Execute Replace:=wdReplaceAll
' Replace with tab
Selection.Find.text = "&#9;"
Selection.Find.Replacement.text = "^t"
Selection.Find.Execute Replace:=wdReplaceAll
With Selection.Find
.text = ""
.MatchWildcards = False
.Replacement.text = ""
.ClearFormatting
.Replacement.ClearFormatting
End With
' This change has been dropped for the moment.
' It was meant to try to overcome the problem with Word not updating field codes properly.
'' Format footer section
'Selection.EndKey Unit:=wdStory
'WordBasic.ViewFooterOnly
'Selection.WholeStory
'Selection.Fields.Update
' Clear out the clipboard
Call clearClipBoard
Exit Sub
errorHandler:
showError "formatDocument"
Resume
End Sub
' Process the request for data.
' Return values are:
' 1 - Success
' 0 - No change to document (IsValid was false etc.)
' -1 - Error occured after the document was changed
Private Function getData(Optional fieldPrefix As String = "") As Integer
On Error GoTo errorHandler:
Dim mainRecordSetData As Scripting.Dictionary
Dim formField As formField
Dim contentField As ContentControl
Dim formFieldName, fieldName, fieldValue As String
Dim message As String
Dim currentSection As section
Dim currentHeader As headerFooter
Dim currentFooter As headerFooter
Dim recordsetName As String
Dim ok As Boolean
' Up to a certain point, errors result in no change to the document
getData = 0
Set mainRecordSetData = getPOSSEMainRecordsetData()
' Check if a validation message exists for the current prefix.
If Len(fieldPrefix) > 0 Then
For Each formField In ActiveDocument.FormFields
ok = checkPrefix(fieldPrefix, Trim(formField.range.text))
If ok Then
Exit For
End If
Next
If ok And mainRecordSetData.Exists(fieldPrefix & "IsValid") Then
If Len(mainRecordSetData.Item(fieldPrefix & "IsValid")) > 0 Then
MsgBox (mainRecordSetData.Item(fieldPrefix & "IsValid"))
Exit Function
End If
End If
End If
' Check if a recipient recordset as been declared.
recordsetName = Props.PosseRecipientRecordset
If Len(recordsetName) = 0 Then
recordsetName = "NoRecipient"
End If
' Create the images cache.
Set Images = New Scripting.Dictionary
Images.CompareMode = vbTextCompare
' Reset data tables.
Call resetDataTables(fieldPrefix)
' Process data tables.
Call getTableData(fieldPrefix, ActiveDocument.Tables, mainRecordSetData, message)
' From this point on an error can result in the document being (incompletely) changed
getData = -1
' Substitute each form field with data from posse.
For Each formField In ActiveDocument.FormFields
formFieldName = Trim(formField.range.text)
' Ignore blank fields.
If Len(formFieldName) > 0 Then
' If the default text of the form field has not been set Trim still returns a string of blanks.
' Also, allow for checkbox fields.
If Asc(Left(formFieldName, 1)) <> 32 And Asc(Left(formFieldName, 1)) <> 21 Then
ok = checkPrefix(fieldPrefix, formFieldName)
If ok Then
' Check for recipient recordset fields.
If InStr(1, formFieldName, recordsetName & ".") > 0 Then
ok = False
End If
End If
If ok Then
If LCase(Left(formFieldName, 6)) = "image:" Then
fieldName = Mid(formFieldName, 7)
Else
fieldName = formFieldName
End If
' Replace the field with the data.
If Not mainRecordSetData.Exists(fieldName) Then
If message = "" Then
message = "ObjectId: " & Props.PosseDataSourceId & vbCrLf & _
"Primary record set: " & Props.PosseRecordset & vbCrLf & _
"Recipient record set: " & Props.PosseRecipientRecordset & vbCrLf & _
"The data does not contain a value for the following form field(s):" & vbCrLf
End If
If InStr(1, message, formFieldName & vbCrLf) = 0 Then
message = message & formFieldName & vbCrLf
End If
Else
fieldValue = mainRecordSetData.Item(fieldName)
If LCase(Left(formFieldName, 6)) = "image:" Then
Call getImage(fieldValue, formField.range)
Else
formField.range.text = fieldValue
End If
End If
End If
End If
End If
Next
' Substitute each content field with data from posse.
Call replaceContentFields(fieldPrefix, ActiveDocument.contentControls, mainRecordSetData, message)
' Now look in the header and footer for fieldnames delimited by {}
' Headers and footers cannot have Form Fields, so we'll look for {token} instead
For Each currentSection In ActiveDocument.Sections
' Loop through all the headers in this section
For Each currentHeader In currentSection.Headers
Call replaceTokens(fieldPrefix, currentHeader, mainRecordSetData, message)
Call replaceContentFields(fieldPrefix, currentHeader.range.contentControls, mainRecordSetData, message)
Next
' Loop through all the footers in this section
For Each currentFooter In currentSection.Footers
Call replaceTokens(fieldPrefix, currentFooter, mainRecordSetData, message)
Call replaceContentFields(fieldPrefix, currentFooter.range.contentControls, mainRecordSetData, message)
Next
' Remove blank headers and footers
ActiveWindow.View.Type = wdPrintView
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.WholeStory
Selection.fields.Update
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageFooter
Selection.WholeStory
Selection.fields.Update
Next
' Close header and footer view and set to main document view.
ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
' Process recipients.
Call getRecipientData(fieldPrefix, message)
' Format Document
Call formatDocument
' Delete temporary image data files.
deleteImageFiles
' Get rid of anything left in the clipboard
Call clearClipBoard
' Display any messages.
If message <> "" Then
MsgBox (message)
Else
' It worked!
getData = 1
End If
Exit Function
errorHandler:
showError "getData"
End Function
Private Function getDataTableCommentIndex(id As String)
Dim result As Long
Dim index As Integer
Dim table As table
For index = 1 To ActiveDocument.Comments.count
If ActiveDocument.Comments.Item(index).range.Tables.count > 0 Then
Set table = ActiveDocument.Comments.Item(index).range.Tables.Item(1)
If table.Descr = id Then
result = index
Exit For
End If
End If
Next
getDataTableCommentIndex = result
End Function
' Save document and return a Byte containing the entire document
Private Function getDocumentAsByte() As Variant
Dim Document() As Byte
Dim fileNumber As Integer
' Allows caller to do a UBound > 0 even if this function fails
getDocumentAsByte = StrConv("", vbFromUnicode)
' Get the document
If saveAsUniqueName() Then
fileNumber = FreeFile()
ReDim Document(1 To FileLen(ActiveDocument.FullName))
Open ActiveDocument.FullName For Binary As fileNumber
Get fileNumber, 1, Document
Close (fileNumber)
getDocumentAsByte = Document
Else
MsgBox ("Unable to save temporary copy of document.")
End If
End Function
' Returns the specified image.
Private Sub getImage(documentId As Variant, range As range)
On Error GoTo errorHandler:
Dim data() As Byte
Dim imageFile As String
Dim image As InlineShape
Dim oldImage As InlineShape
If Not (IsNull(documentId) Or documentId = "") Then
If Images.Exists(documentId) Then
imageFile = Images(documentId)
Else
data = getPOSSEImage(documentId)
imageFile = ActiveDocument.Path & "\ImageBuffer" + documentId + ".dat"
saveBinaryData imageFile, data
' Cache the image file name.
Call Images.Add(documentId, imageFile)
End If
If range.ParentContentControl Is Nothing Then
' Remove the placeholder.
range.text = ""
Set image = ActiveDocument.InlineShapes.AddPicture(imageFile, False, True, range)
Else
If range.InlineShapes.count > 0 Then
Set oldImage = range.InlineShapes.Item(1)
End If
Set image = range.InlineShapes.AddPicture(imageFile, False, True)
' If a previous image existed and was not a place holder then remove it.
If range.InlineShapes.count > 1 Then
oldImage.Delete
End If
End If
ElseIf range.ParentContentControl Is Nothing Then
' Remove the placeholder.
range.text = ""
End If
Exit Sub
errorHandler:
showError "getImage"
End Sub
Private Function getPOSSEMainRecordsetData() As Scripting.Dictionary
On Error GoTo errorHandler:
'Dim xml As New DOMDocument
If Props.PosseSendCredentials Then
If Len(Auth.AuthString) = 0 Then
If Not showCredentialsForm() Then
Exit Function
End If
End If
End If
' Call the web service and load the result into the xml dom.
Ajax.Open "GET", Props.PosseBaseURI & "/data/" & Props.PosseDataSourceId & "/" & _
Props.PosseRecordset & "?sessionToken=" & Props.PosseSessionToken & "&PosseTraceKey=" & getTraceKey() & "&" & Auth.AuthString, False
Ajax.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
Ajax.setRequestHeader "Accept", "application/xml"
Ajax.setRequestHeader "Cache-Control", "no-cache"
Ajax.setRequestHeader "Pragma", "no-cache"
Ajax.setRequestHeader "If-Modified-Since", "Sat
1 Jan 2000 00:00:00 GMT"
Ajax.send
Set getPOSSEMainRecordsetData = parseXML(Ajax.responseXML).Item(1)
Exit Function
errorHandler:
showError "getPOSSEMainRecordsetData"
End Function
Private Function getPOSSEImage(documentId As Variant) As Byte()
On Error GoTo errorHandler:
If Props.PosseSendCredentials Then
If Len(Auth.AuthString) = 0 Then
If Not showCredentialsForm() Then
Exit Function
End If
End If
End If
' Call the web service and load the result into the xml dom.
Ajax.Open "GET", Props.PosseBaseURI & "/image/" & documentId & "?sessionToken=" & Props.PosseSessionToken & "&PosseTraceKey=" & getTraceKey() & "&" & Auth.AuthString, False
Ajax.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
Ajax.setRequestHeader "Cache-Control", "no-cache"
Ajax.setRequestHeader "Pragma", "no-cache"
Ajax.setRequestHeader "If-Modified-Since", "Sat
1 Jan 2000 00:00:00 GMT"
Ajax.send
' The string comes back with quotes, which have to be stripped.
getPOSSEImage = base64Decode(Mid(Ajax.responseText, 2, Len(Ajax.responseText) - 2))
Exit Function
errorHandler:
showError "getPOSSEImage"
End Function
Private Function getPOSSETableData(recordsetName As String) As Scripting.Dictionary
On Error GoTo errorHandler:
If Props.PosseSendCredentials Then
If Len(Auth.AuthString) = 0 Then
If Not showCredentialsForm() Then
Exit Function
End If
End If
End If
' Call the web service and load the result into the xml dom.
Ajax.Open "GET", Props.PosseBaseURI & "/data/" & Props.PosseDataSourceId & "/" & _
recordsetName & "?sessionToken=" & Props.PosseSessionToken & "&PosseTraceKey=" & getTraceKey() & "&" & Auth.AuthString, False
Ajax.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
Ajax.setRequestHeader "Accept", "application/xml"
Ajax.setRequestHeader "Cache-Control", "no-cache"
Ajax.setRequestHeader "Pragma", "no-cache"
Ajax.setRequestHeader "If-Modified-Since", "Sat
1 Jan 2000 00:00:00 GMT"
Ajax.send
Set getPOSSETableData = parseXML(Ajax.responseXML)
Exit Function
errorHandler:
showError "getPOSSETableData"
End Function
' Process recipient data.
Private Sub getRecipientData(fieldPrefix As String, message As String)
On Error GoTo errorHandler:
Dim recipientData As Scripting.Dictionary
Dim formField As formField
Dim contentField As ContentControl
Dim formFieldName As String
Dim fieldName As String
Dim fieldValue As Variant
Dim recordsetName As String
Dim index As Integer
Dim section As section
Dim ok As Boolean
Dim recipientRange As range
Dim idx As Long
recordsetName = Props.PosseRecipientRecordset
ok = False
' Only process if a recipient recordset was provided and recipient fields are present.
If Len(recordsetName) > 0 Then
For Each formField In ActiveDocument.FormFields
formFieldName = Trim(formField.range.text)
ok = checkPrefix(fieldPrefix, formFieldName)
If ok Then
If InStr(1, formFieldName, recordsetName & ".") = 0 Then
ok = False
Else
Exit For
End If
End If
Next
If Not ok Then
For Each contentField In ActiveDocument.contentControls
formFieldName = Trim(contentField.Title)
ok = checkPrefix(fieldPrefix, formFieldName)
If ok Then
If InStr(1, formFieldName, recordsetName & ".") = 0 Then
ok = False
Else
Exit For
End If
End If
Next
End If
If ok Then
Set recipientData = getPOSSETableData(recordsetName)
Set recipientRange = ActiveDocument.range(0, 0)
' Process the data.
If recipientData.count > 0 Then
' Add a section break to restart page numbering.
Set section = ActiveDocument.Sections.Add()
section.PageSetup.SectionStart = wdSectionContinuous
section.Headers(wdHeaderFooterPrimary).LinkToPrevious = False
section.Footers(wdHeaderFooterPrimary).LinkToPrevious = False
section.Footers(wdHeaderFooterPrimary).PageNumbers.RestartNumberingAtSection = True
Set section = ActiveDocument.Sections.Add()
section.PageSetup.SectionStart = wdSectionContinuous
section.Headers(wdHeaderFooterPrimary).LinkToPrevious = False
section.Footers(wdHeaderFooterPrimary).LinkToPrevious = False
section.Footers(wdHeaderFooterPrimary).PageNumbers.RestartNumberingAtSection = True
Selection.WholeStory
Selection.Copy
recipientRange.WholeStory
For index = 1 To recipientData.count
' Substitute each form field with data from posse.
For Each formField In recipientRange.FormFields
formFieldName = Trim(formField.range.text)
' Ignore blank fields.
If Len(formFieldName) > 0 Then
' If the default text of the form field has not been set Trim still returns a string of blanks.
' Also, allow for checkbox fields.
If Asc(Left(formFieldName, 1)) <> 32 And Asc(Left(formFieldName, 1)) <> 21 Then
ok = checkPrefix(fieldPrefix, formFieldName)
If ok Then
If InStr(1, formFieldName, recordsetName & ".") > 0 Then
fieldValue = getRecipientValue(recipientData.Item(index), formFieldName)
End If
' Replace the field with the data.
If IsNull(fieldValue) Or fieldValue = "" Then
If message = "" Then
message = "ObjectId: " & Props.PosseDataSourceId & vbCrLf & _
"Primary record set: " & Props.PosseRecordset & vbCrLf & _
"Recipient record set: " & Props.PosseRecipientRecordset & vbCrLf & _
"The data does not contain a value for the following form field(s):" & vbCrLf
End If
If InStr(1, message, formFieldName & vbCrLf) = 0 Then
message = message & formFieldName & vbCrLf
End If
ElseIf LCase(Left(formFieldName, 6)) = "image:" Then
Call getImage(fieldValue, formField.range)
Else
formField.range.text = fieldValue
End If
End If
End If
End If
Next
' Substitute each content field with data from posse.
For Each contentField In recipientRange.contentControls
formFieldName = Trim(contentField.Title)
' Ignore blank fields.
If Len(formFieldName) > 0 Then
ok = checkPrefix(fieldPrefix, formFieldName)
If ok Then
If InStr(1, formFieldName, recordsetName & ".") > 0 Then
fieldValue = getRecipientValue(recipientData.Item(index), formFieldName)
contentField.Temporary = True
End If
' Replace the field with the data.
If IsNull(fieldValue) Or fieldValue = "" Then
If message = "" Then
message = "ObjectId: " & Props.PosseDataSourceId & vbCrLf & _
"Primary record set: " & Props.PosseRecordset & vbCrLf & _
"Recipient record set: " & Props.PosseRecipientRecordset & vbCrLf & _
"The data does not contain a value for the following form field(s):" & vbCrLf
End If
If InStr(1, message, formFieldName & vbCrLf) = 0 Then
message = message & formFieldName & vbCrLf
End If
ElseIf contentField.Type = wdContentControlCheckBox Then
contentField.Checked = fieldValue
ElseIf contentField.Type = wdContentControlPicture And LCase(Left(formFieldName, 6)) = "image:" Then
Call getImage(fieldValue, contentField.range)
ElseIf Len(fieldValue) = 0 Then
' If the value is an empty string the placeholder text will not be removed.
contentField.range.text = " "
Else
contentField.range.text = fieldValue
End If
End If
End If
Next
If index < recipientData.count Then
' Duplicate the document.
Set recipientRange = ActiveDocument.range(recipientRange.End - 1, recipientRange.End)
Selection.EndKey (wdStory)
Selection.InsertBreak (wdPageBreak)
Selection.Paste
idx = recipientRange.EndOf(wdStory, wdExtend)
End If
Next
End If
End If
End If
Exit Sub
errorHandler:
showError "getRecipientData"
End Sub
' Return a recipient value.
Private Function getRecipientValue(recipientRow As Scripting.Dictionary, formFieldName As String) As Variant
On Error GoTo errorHandler:
Dim tableFormFieldName As String
' Seperate the recordset name from the form field name.
tableFormFieldName = Mid(formFieldName, InStr(1, formFieldName, ".") + 1)
If LCase(Left(tableFormFieldName, 6)) = "image:" Then
tableFormFieldName = Mid(tableFormFieldName, 7)
End If
If recipientRow.Exists(tableFormFieldName) Then
getRecipientValue = recipientRow.Item(tableFormFieldName)
Else
getRecipientValue = Null
End If
Exit Function
errorHandler:
showError "getRecipientValue"
End Function
' Process table data.
Private Sub getTableData(fieldPrefix As String, dataTables As Object, mainRecordSetData As Scripting.Dictionary, message As String)
On Error GoTo errorHandler:
Dim dataTable As table
Dim tableRow As Row
Dim tableCell As Cell
Dim formField As formField
Dim contentField As ContentControl
Dim formFieldName As String
Dim fieldValue As Variant
Dim recordsets As Scripting.Dictionary
Dim firstRows As Scripting.Dictionary
Dim recipientRecordsetName As String
Dim ok, fieldExists As Boolean
Dim index As Integer
' Check if the document contains any tables.
If dataTables.count > 0 Then
Set recordsets = New Scripting.Dictionary
recordsets.CompareMode = vbTextCompare
Set firstRows = New Scripting.Dictionary
firstRows.CompareMode = vbTextCompare
' Check if a recipient recordset as been declared.
recipientRecordsetName = Props.PosseRecipientRecordset
If Len(recipientRecordsetName) = 0 Then
recipientRecordsetName = "NoRecipient"
End If
' Process each cell of each table.
For index = 1 To dataTables.count
Set dataTable = dataTables.Item(index)
' Process nested data tables.
Call getTableData(fieldPrefix, dataTable.Tables, mainRecordSetData, message)
On Error GoTo tableError:
' Clear the table id so all rows it will be processed.
dataTable.id = ""
For Each tableRow In dataTable.rows
On Error GoTo errorHandler:
For Each tableCell In tableRow.Cells
' Substitute each form field with data from posse.
For Each formField In tableCell.range.FormFields
formFieldName = Trim(formField.range.text)
' Ignore blank fields.
If Len(formFieldName) > 0 Then
' If the default text of the form field has not been set Trim still returns a string of blanks.
' Also, allow for checkbox fields.
If Asc(Left(formFieldName, 1)) <> 32 And Asc(Left(formFieldName, 1)) <> 21 Then
ok = checkPrefix(fieldPrefix, formFieldName)
If ok Then
' Check for recipient recordset fields.
If InStr(1, formFieldName, recipientRecordsetName & ".") > 0 Then
ok = False
End If
End If
If ok Then
fieldValue = Null
If LCase(Left(formFieldName, 6)) = "image:" Then
If mainRecordSetData.Exists(Mid(formFieldName, 7)) Then
fieldValue = mainRecordSetData.Item(Mid(formFieldName, 7))
End If
ElseIf InStr(1, formFieldName, ".") > 0 Then
fieldValue = getTableValue(tableRow, recordsets, firstRows, formFieldName, index)
ElseIf mainRecordSetData.Exists(formFieldName) Then
fieldValue = mainRecordSetData.Item(formFieldName)
End If
' Replace the field with the data.
If IsNull(fieldValue) Then
' If the recordset contains no data then just remove the field.
If InStr(1, formFieldName, ".") > 0 And Not checkRecordsets(recordsets, formFieldName) Then
formField.range.text = ""
Else
If message = "" Then
message = "ObjectId: " & Props.PosseDataSourceId & vbCrLf & _
"Primary record set: " & Props.PosseRecordset & vbCrLf & _
"Recipient record set: " & Props.PosseRecipientRecordset & vbCrLf & _
"The data does not contain a value for the following form field(s):" & vbCrLf
End If
If InStr(1, message, formFieldName & vbCrLf) = 0 Then
message = message & formFieldName & vbCrLf
End If
End If
ElseIf InStr(1, LCase(formFieldName), "image:") > 0 Then
Call getImage(fieldValue, formField.range)
Else
formField.range.text = fieldValue
End If
End If
End If
End If
Next
' Substitute each content field with data from posse.
For Each contentField In tableCell.range.contentControls
formFieldName = Trim(contentField.Title)
' Ignore blank fields.
If Len(formFieldName) > 0 Then
ok = checkPrefix(fieldPrefix, formFieldName)
If ok Then
' Check for recipient recordset fields.
If InStr(1, formFieldName, recipientRecordsetName & ".") > 0 Then
ok = False
End If
End If
If ok Then
fieldValue = Null
If LCase(Left(formFieldName, 6)) = "image:" Then
If mainRecordSetData.Exists(Mid(formFieldName, 7)) Then
fieldValue = mainRecordSetData.Item(Mid(formFieldName, 7))
End If
ElseIf InStr(1, formFieldName, ".") > 0 Then
fieldValue = getTableValue(tableRow, recordsets, firstRows, formFieldName, index)
ElseIf mainRecordSetData.Exists(formFieldName) Then
fieldValue = mainRecordSetData.Item(formFieldName)
End If
' Replace the field with the data.
If IsNull(fieldValue) Then
' If the recordset contains no data then just remove the field.
If InStr(1, formFieldName, ".") > 0 And Not checkRecordsets(recordsets, formFieldName) Then
If contentField.Type = wdContentControlCheckBox Then
contentField.Checked = False
ElseIf contentField.Type = wdContentControlPicture Then
contentField.range.InlineShapes.Item(1).Delete
Else
' If the value is an empty string the placeholder text will not be removed.
contentField.range.text = " "
End If
Else
If message = "" Then
message = "ObjectId: " & Props.PosseDataSourceId & vbCrLf & _
"Primary record set: " & Props.PosseRecordset & vbCrLf & _
"Recipient record set: " & Props.PosseRecipientRecordset & vbCrLf & _
"The data does not contain a value for the following form field(s):" & vbCrLf
End If
If InStr(1, message, formFieldName & vbCrLf) = 0 Then
message = message & formFieldName & vbCrLf
End If
End If
ElseIf contentField.Type = wdContentControlCheckBox Then
contentField.Checked = fieldValue
ElseIf contentField.Type = wdContentControlPicture And InStr(1, LCase(formFieldName), "image:") > 0 Then
Call getImage(fieldValue, contentField.range)
ElseIf Len(fieldValue) = 0 Then
' If the value is an empty string the placeholder text will not be removed.
contentField.range.text = " "
Else
contentField.range.text = fieldValue
End If
End If
End If
Next
Next
On Error GoTo tableError:
Next
returnFromTableError:
On Error GoTo errorHandler:
Next
Set recordsets = Nothing
Set firstRows = Nothing
End If
Exit Sub
errorHandler:
showError "getTableData"
MsgBox (Err.Number & ": " & Err.Description)
Exit Sub
tableError:
'If the table has vertically merged rows, catch the error and continue with the next table.
If Err.Number = 5991 Then
Err.Clear
GoTo returnFromTableError:
Else
showError "getTableData"
End If
End Sub
' Return a table value.
Private Function getTableValue(tableRow As Row, recordsets As Scripting.Dictionary, _
firstRows As Scripting.Dictionary, formFieldName As String, tableIndex) As Variant
On Error GoTo errorHandler:
Dim count As Integer
Dim footerRows As Integer
Dim recordsetName As String
Dim tableFormFieldName As String
Dim recordsetData, recordsetRow As Scripting.Dictionary
Dim fieldValue As Variant
Dim fieldExists As Boolean
fieldValue = Null
' Seperate the recordset name from the form field name.
recordsetName = Left(formFieldName, InStr(1, formFieldName, ".") - 1)
tableFormFieldName = Mid(formFieldName, InStr(1, formFieldName, ".") + 1)
' If the data for the recordset has already been retrieved than use it, eitherwise get it.
If recordsets.Exists(recordsetName) Then
Set recordsetData = recordsets(recordsetName)
Else
Set recordsetData = getPOSSETableData(recordsetName)
' Cache the dom.
Call recordsets.Add(recordsetName, recordsetData)
End If
If Len(tableRow.Parent.id) = 0 Then
' Set the table id so we know this table has been processed.
tableRow.Parent.id = tableIndex
' Process the first row of data.
If recordsetData.count > 0 Then
Set recordsetRow = recordsetData.Item(1)
' Store first data row position.
Call firstRows.Add(tableRow.Parent.id, tableRow.index - 1)
' Duplicate the template row for each row of data.
If recordsetData.count > 1 Then
Call tableRow.Select
Call Selection.Copy
footerRows = tableRow.Parent.rows.count - tableRow.index
' Insert a temporary blank row.
Call Selection.InsertRowsBelow
For count = 2 To recordsetData.count
Call Selection.Paste
Next
' Remove the temporary blank row.
Call tableRow.Parent.rows(tableRow.Parent.rows.count - footerRows).Delete
End If
End If
Else
' Get the data element for the current table row.
If recordsetData.count > 0 Then
Set recordsetRow = recordsetData.Item(tableRow.index - firstRows(tableRow.Parent.id))
End If
End If
If Not recordsetRow Is Nothing Then
If LCase(Left(tableFormFieldName, 6)) = "image:" Then
If recordsetRow.Exists(Mid(tableFormFieldName, 7)) Then
fieldValue = recordsetRow.Item(Mid(tableFormFieldName, 7))
End If
ElseIf recordsetRow.Exists(tableFormFieldName) Then
fieldValue = recordsetRow.Item(tableFormFieldName)
End If
End If
' Return the value.
getTableValue = fieldValue
Exit Function
errorHandler:
showError "getTableValue"
End Function
' This function uses Windows API GetTempPath to get the temporary folder
Private Function getTmpPath()
Dim sFolder As String ' Name of the folder
Dim lRet As Long ' Return Value
sFolder = String(MAX_PATH, 0)
lRet = GetTempPath(MAX_PATH, sFolder)
If lRet <> 0 Then
getTmpPath = Left(sFolder, InStr(sFolder, Chr(0)) - 2)
Else
getTmpPath = vbNullString
End If
End Function
Public Sub ReplaceList(matchString As String, replacementString As String, listStyle As Integer, _
listName As String, styleString As String, Optional restartNumbering As Boolean = False)
On Error GoTo errorHandler
' List Style Types:
' 1 Number Paren: 1)
' 2 Alpha Paren: a)
' 3 Roman Paren: i)
' 4 Paren Number Paren: (1)
' 5 Paren Alpha Paren: (a)
' 6 Paren Roman Paren: (i)
' 7 Number Dot: 1.
' 8 Alpha Dot: a.
' 9 Roman Dot: i.
Dim listNumStyle As String
Dim listNumText As String
Dim newField
Dim findSuccessful
If styleExists(styleString) Then
listNumStyle = "LISTNUM """ & listName & """ \l " & listStyle
Selection.HomeKey Unit:=wdStory
With Selection.Find
.text = matchString
.Replacement.text = replacementString
.Replacement.style = ActiveDocument.Styles(styleString)
.MatchWildcards = True
findSuccessful = .Execute
End With
While findSuccessful
With Selection
.Collapse Direction:=wdCollapseStart
If restartNumbering Then
listNumText = listNumStyle & " \s 1"
Else
listNumText = listNumStyle
End If
newField = .fields.Add(range:=Selection.range, Type:=wdFieldEmpty, text:=listNumText, PreserveFormatting:=False)
.Find.Execute Replace:=wdReplaceOne
.Collapse Direction:=wdCollapseEnd
findSuccessful = .Find.Execute
End With
Wend
End If
Exit Sub
errorHandler:
If Err.Number = ERR_MEMBER_NOT_FOUND Then
Debug.Print "Warning: Style '" & styleString & "' was not found in the document."
Else
showError "ReplaceList", "Can't replace '" & replacementString & "' with the style '" + styleString + "'"
End If
End Sub
'Replace Text With Style
Public Sub ReplaceTextWithStyle(matchString As String, replacementString As String, styleString As String)
On Error GoTo errorHandler
If styleExists(styleString) Then
Selection.WholeStory
With Selection.Find
.text = matchString
.Replacement.text = replacementString
.Replacement.style = ActiveDocument.Styles(styleString)
.MatchWildcards = True
End With
Selection.Find.Execute Replace:=wdReplaceAll
End If
Exit Sub
errorHandler:
If Err.Number = ERR_MEMBER_NOT_FOUND Then
Debug.Print "Warning: Style '" & styleString & "' was not found in the document."
Else
showError "ReplaceTextWithStyle"
"Can't replace '" & replacementString & "' with the style '" + styleString + "'"
End If
End Sub
Private Function parseXML(XMLDom As DOMDocument60) As Scripting.Dictionary
Dim dict As New Scripting.Dictionary
Dim dictRow As Scripting.Dictionary
Dim rows
fields As IXMLDOMNodeList
Dim i
j As Long
dict.CompareMode = vbTextCompare
' It is possible that a recordset that doesn't exist has been referenced.
If XMLDom.ChildNodes.Length > 0 Then
Set rows = XMLDom.ChildNodes.Item(0).ChildNodes
For i = 1 To rows.Length
Set dictRow = New Scripting.Dictionary
dictRow.CompareMode = vbTextCompare
Set fields = rows.Item(i - 1).ChildNodes
For j = 1 To fields.Length
If fields.Item(j - 1).ChildNodes.Length > 1 Then
Call dictRow.Add(fields.Item(j - 1).ChildNodes.Item(0).text
fields.Item(j - 1).ChildNodes.Item(1).text)
End If
Next
Call dict.Add(i, dictRow)
Next
Set rows = Nothing
Set fields = Nothing
End If
Set parseXML = dict
End Function
Private Sub replaceContentFields(fieldPrefix As String, contentControls As Object, mainRecordSetData As Scripting.Dictionary, message As String)
On Error GoTo errorHandler:
Dim contentField As ContentControl
Dim formFieldName
fieldName
fieldValue As String
Dim recipientRecordsetName As String
Dim ok As Boolean
' Check if a recipient recordset as been declared.
recipientRecordsetName = Props.PosseRecipientRecordset
If Len(recipientRecordsetName) = 0 Then
recipientRecordsetName = "NoRecipient"
End If
' Substitute each content field with data from posse.
For Each contentField In contentControls
formFieldName = Trim(contentField.Title)
' Ignore blank fields and fields for tables.
If Len(formFieldName) > 0 And InStr(1, formFieldName, ".") = 0 Then
ok = checkPrefix(fieldPrefix, formFieldName)
If ok Then
' Check for recipient recordset fields.
If InStr(1, formFieldName, recipientRecordsetName & ".") > 0 Then
ok = False
End If
End If
If ok Then
If LCase(Left(formFieldName, 6)) = "image:" Then
fieldName = Mid(formFieldName, 7)
Else
fieldName = formFieldName
End If
' Replace the field with the data.
If Not mainRecordSetData.Exists(fieldName) Then
If message = "" Then
message = "ObjectId: " & Props.PosseDataSourceId & vbCrLf & _
"Primary record set: " & Props.PosseRecordset & vbCrLf & _
"Recipient record set: " & Props.PosseRecipientRecordset & vbCrLf & _
"The data does not contain a value for the following form field(s):" & vbCrLf
End If
If InStr(1, message, formFieldName & vbCrLf) = 0 Then
message = message & formFieldName & vbCrLf
End If
Else
fieldValue = mainRecordSetData.Item(fieldName)
If contentField.Type = wdContentControlCheckBox Then
contentField.Checked = fieldValue
ElseIf contentField.Type = wdContentControlPicture And LCase(Left(formFieldName, 6)) = "image:" Then
Call getImage(fieldValue, contentField.range)
ElseIf Len(fieldValue) = 0 Then
' If the value is an empty string the placeholder text will not be removed.
contentField.range.text = " "
Else
contentField.range.text = fieldValue
End If
End If
End If
End If
Next
Exit Sub
errorHandler:
showError "replaceContentFields"
End Sub
' Process header and footer tokens.
Private Sub replaceTokens(fieldPrefix As String, headerFooter As headerFooter, mainRecordSetData As Scripting.Dictionary, message As String)
Dim fieldValue As Variant
Dim token As String
Dim i As Long
Dim wordCount As Long
Dim isImage As Boolean
Dim ok As Boolean
i = 1
wordCount = headerFooter.range.Words.count
If wordCount = 1 And headerFooter.range.Words(1).text = Chr(13) Then
'skip because there is only a carriage return to insert and nothing else
Else
While i <= wordCount
isImage = False
ok = True
If (Trim(headerFooter.range.Words(i).text) = "{" Or Trim(headerFooter.range.Words(i).text) = "{[") _
And headerFooter.range.Words.count >= i + 2 Then
If Trim(headerFooter.range.Words(i + 2).text) = "}" Or (LCase(Trim(headerFooter.range.Words(i + 1).text)) = "image" And _
Trim(headerFooter.range.Words(i + 2).text) = ":") Or _
Trim(headerFooter.range.Words(i + 2).text) = "]" Then
' Check for a prefix.
If Len(fieldPrefix) = 0 Then
If Trim(headerFooter.range.Words(i).text) = "{[" Then
ok = False
End If
ElseIf Trim(headerFooter.range.Words(i).text) = "{[" And _
Trim(headerFooter.range.Words(i + 2).text) = "]" And _
LCase(Trim(headerFooter.range.Words(i + 1).text)) = LCase(fieldPrefix) Then
headerFooter.range.Words(i + 1).Delete
headerFooter.range.Words(i).text = "{"
token = headerFooter.range.Words(i + 1)
ElseIf Len(fieldPrefix) > 0 Then
ok = False
End If
If ok Then
' Replace the token with its value from POSSE
If LCase(Trim(headerFooter.range.Words(i + 1).text)) = "image" And _
Trim(headerFooter.range.Words(i + 2).text) = ":" Then
isImage = True
token = headerFooter.range.Words(i + 3)
Else
token = headerFooter.range.Words(i + 1)
End If
fieldValue = Null
If mainRecordSetData.Exists(token) Then
fieldValue = mainRecordSetData.Item(token)
End If
' Replace the field with the data.
If IsNull(fieldValue) Or fieldValue = "" Then
' Keep track of the problems
If message = "" Then
message = "ObjectId: " & Props.PosseDataSourceId & vbCrLf & _
"Primary record set: " & Props.PosseRecordset & vbCrLf & _
"Recipient record set: " & Props.PosseRecipientRecordset & vbCrLf & _
"The data does not contain a value for the following form field(s):" & vbCrLf
End If
message = message & token & vbCrLf
Else
' Replace the token with the data value
If isImage Then
headerFooter.range.Words(i + 3).Delete
headerFooter.range.Words(i + 2).Delete
headerFooter.range.Words(i + 1).Delete
' Pass the } to be replaced with the image.
Call getImage(fieldValue, headerFooter.range.Words(i + 1))
Else
headerFooter.range.Words(i + 1).Delete
' Replace } with the data value.
If Right(headerFooter.range.Words(i + 1).text, 1) = " " Then
headerFooter.range.Words(i + 1) = fieldValue & _
Mid(headerFooter.range.Words(i + 1).text, InStr(1, headerFooter.range.Words(i + 1).text, " ", vbTextCompare))
Else
headerFooter.range.Words(i + 1) = fieldValue
End If
End If
' Now delete the {. If you do this before replacement
any text to the left may be removed as well.
headerFooter.range.Words(i).Delete
' Word counts words in a very specific manner, so get it to tell us how many words we added/removed
' and then set the pointer to skip over them on the next pass
' i = i + headerFooter.range.Words.count - wordCount + 2
wordCount = headerFooter.range.Words.count
End If
End If
End If
End If
i = i + 1
Wend
End If 'Valid insertion data
End Sub
Private Sub resetDataTables(fieldPrefix As String)
On Error GoTo errorHandler:
Dim dataTable As table
Dim tableRow As Row
Dim tableCell As Cell
Dim copyTable As table
Dim index As Integer
Dim copyIndex As Integer
Dim rowIndex As Integer
Dim hasContentFields As Boolean
Dim position As Long
Dim comment As comment
Dim formFieldName As String
Dim ok As Boolean
Dim contentField As ContentControl
For index = 1 To ActiveDocument.Tables.count
Set dataTable = ActiveDocument.Tables.Item(index)
copyIndex = getDataTableCommentIndex(Str(index))
If copyIndex = 0 Then
hasContentFields = False
On Error GoTo tableError:
For Each tableRow In dataTable.rows
On Error GoTo errorHandler:
For Each tableCell In tableRow.Cells
If tableCell.range.contentControls.count > 0 Then
hasContentFields = True
Exit For
End If
Next
If hasContentFields Then
Exit For
End If
Next
If hasContentFields Then
dataTable.Select
Selection.Copy
If ActiveDocument.Comments.count = 0 Then
ActiveWindow.View.ShowComments = False
End If
Set comment = ActiveDocument.Comments.Add(ActiveDocument.range(dataTable.range.End, dataTable.range.End))
comment.range.Select
Selection.Paste
comment.range.Tables.Item(comment.range.Tables.count).Descr = Str(index)
End If
Else
ok = True
On Error GoTo tableError:
For Each tableRow In dataTable.rows
On Error GoTo errorHandler:
For Each tableCell In tableRow.Cells
For Each contentField In tableCell.range.contentControls
formFieldName = Trim(contentField.Title)
' Ignore blank fields.
If Len(formFieldName) > 0 Then
ok = checkPrefix(fieldPrefix, formFieldName)
If Not ok Then
Exit For
End If
End If
Next
If Not ok Then
Exit For
End If
Next
If Not ok Then
Exit For
End If
Next
If ok Then
Set copyTable = ActiveDocument.Comments.Item(copyIndex).range.Tables.Item(1)
copyTable.Select
Selection.Copy
For rowIndex = dataTable.rows.count - 1 To 1 Step -1
dataTable.rows.Item(rowIndex).Delete
Next
dataTable.Select
Selection.Paste
dataTable.rows.Item(dataTable.rows.count).Delete
End If
End If
returnFromTableError:
On Error GoTo errorHandler:
Next
ActiveWindow.View.SplitSpecial = wdPaneNone
Exit Sub
errorHandler:
showError "resetDataTables"
Exit Sub
tableError:
'If the table has vertically merged rows
catch the error and continue with the next table.
If Err.Number = 5991 Then
Err.Clear
GoTo returnFromTableError:
Else
showError "resetDataTables"
End If
End Sub
'Recent browsers don't allow the macro to save within the first 70 seconds of download.
'This function does a save as the first time and then a save on subsequent calls to get around this problem.
Private Function saveAsUniqueName()
Dim x As Integer
Dim tempDir As String
Dim baseFileName As String
Dim originalName As String
Dim FileName As String
Dim tempFullName As String
Dim pos As Integer
Dim extension As Variant
saveAsUniqueName = False
If FileHasUniqueName = False Then
'This is the first save
so save into a new unique file name
x = 0
tempDir = getTmpPath()
baseFileName = ActiveDocument.Name
originalName = ActiveDocument.FullName
pos = InStrRev(baseFileName, ".")
If pos > 0 Then
extension = Mid(baseFileName, pos)
baseFileName = Mid(baseFileName, 1, pos - 1)
End If
tempFullName = tempDir + "\" + baseFileName + extension
On Error GoTo errorHandler:
'Error Handler will keep trying this with a different name until it works
ActiveDocument.SaveAs (tempFullName)
FileHasUniqueName = True
On Error Resume Next
Kill (originalName)
Else
' We've saved successfully at least once, so just do a straight save
ActiveDocument.Save
End If
saveAsUniqueName = True
Exit Function
errorHandler:
'Keep trying different file names until one works
x = x + 1
If x < 199 Then
tempFullName = tempDir & "\" & baseFileName & "[" & x & "]" & extension
Resume
End If
End Function
'Save binary data to a file
Private Sub saveBinaryData(FileName As String, byteArray() As Byte)
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
'Create Stream object
Dim binaryStream
Set binaryStream = New Stream
'Specify stream type - we want To save binary data.
binaryStream.Type = adTypeBinary
'Open the stream And write binary data To the object
binaryStream.Open
binaryStream.Write byteArray
'Save binary data To disk
binaryStream.SaveToFile FileName, adSaveCreateOverWrite
End Sub
' Load the document into Posse.
Private Function saveDocument(Optional fieldPrefix As String = "", Optional saveUnsigned As Boolean = False, Optional saveRevision As Boolean = False)
On Error GoTo errorHandler:
Dim result As String
Dim fileNumber As Integer
Dim Document() As Byte
' Get the document
If Props.PosseSaveAsPDF And fieldPrefix = "Sign" Then
Dim doc As Word.Document
Set doc = Word.Application.ActiveDocument
Dim pdfName As String
pdfName = doc.Path + "\" + doc.Name + ".pdf"
doc.SaveAs2 pdfName, wdFormatPDF
' Now that the PDF is created
we need to convert it to bytes
Dim PDF() As Byte
Dim fileNum As Integer
fileNum = FreeFile()
ReDim PDF(1 To FileLen(pdfName))
Open pdfName For Binary As fileNum
Get fileNum
1
PDF
Close (fileNum)
Document = PDF
Else
Document = getDocumentAsByte()
End If
If UBound(Document) > 0 Then
result = setPOSSEDocument(fieldPrefix, Document, saveUnsigned, saveRevision)
' The result will either be a valid token or an error message.
If IsNumeric(result) Then
saveDocument = result
Else
MsgBox (result)
End If
' If you don't set the flag first save does not actually save if the only change was to a property.
ActiveDocument.Saved = False
If saveAsUniqueName() = False Then
MsgBox ("Unable to save temporary copy of document.")
End If
End If
Exit Function
errorHandler:
showError "saveDocument"
End Function
' Set the userid and password.
Public Sub setCredentials(u As String, p As String)
Auth.UserId = u
Auth.Password = p
CredentialsOK = True
Auth.AuthString = "userId=" & u & "&password=" & p
End Sub
Private Function setPOSSEDocument(prefix As String, Document() As Byte
saveUnsigned As Boolean
saveRevision As Boolean) As String
On Error GoTo errorHandler:
Const STR_BOUNDARY As String = "--3fbd04f5-b1ed-4060-99b9-fca7ff59c113"
Dim messageBody() As Byte
Dim nextPiece() As Byte
If Props.PosseSendCredentials Then
If Len(Auth.AuthString) = 0 Then
If Not showCredentialsForm() Then
Exit Function
End If
End If
End If
Dim urlController As String
urlController = "/document/"
messageBody = toByteArray("--" & STR_BOUNDARY & vbCrLf & _
"Content-Disposition: form-data; name=""prefix""" & vbCrLf & vbCrLf & _
prefix & vbCrLf & _
"--" & STR_BOUNDARY & vbCrLf & _
"Content-Disposition: form-data; name=""docBlob""; filename=""docBlob.docm""" & vbCrLf & _
"Content-Type: application/octet-stream" & vbCrLf & vbCrLf)
Dim uBoundA As Long
Dim lenArrB As Long
uBoundA = UBound(messageBody)
lenArrB = (UBound(Document) - LBound(Document)) + 1
ReDim Preserve messageBody(uBoundA + lenArrB)
CopyMemory ByVal VarPtr(messageBody(uBoundA + 1))
ByVal VarPtr(Document(LBound(Document)))
lenArrB
If saveUnsigned Then
nextPiece = toByteArray(vbCrLf & "--" & STR_BOUNDARY & vbCrLf & _
"Content-Disposition: form-data; name=""unsigned""; filename=""unsigned.ocm""" & vbCrLf & _
"Content-Type: application/octet-stream" & vbCrLf & vbCrLf)
uBoundA = UBound(messageBody)
lenArrB = (UBound(nextPiece) - LBound(nextPiece)) + 1
ReDim Preserve messageBody(uBoundA + lenArrB)
CopyMemory ByVal VarPtr(messageBody(uBoundA + 1))
ByVal VarPtr(nextPiece(LBound(nextPiece)))
lenArrB
uBoundA = UBound(messageBody)
lenArrB = (UBound(UnsignedDocument) - LBound(UnsignedDocument)) + 1
ReDim Preserve messageBody(uBoundA + lenArrB)
CopyMemory ByVal VarPtr(messageBody(uBoundA + 1))
ByVal VarPtr(UnsignedDocument(LBound(UnsignedDocument)))
lenArrB
urlController = "/unsigned/"
End If
nextPiece = toByteArray(vbCrLf & "--" & STR_BOUNDARY & "--" & vbCrLf)
uBoundA = UBound(messageBody)
lenArrB = (UBound(nextPiece) - LBound(nextPiece)) + 1
ReDim Preserve messageBody(uBoundA + lenArrB)
CopyMemory ByVal VarPtr(messageBody(uBoundA + 1))
ByVal VarPtr(nextPiece(LBound(nextPiece)))
lenArrB
' Call the web service and load the result into the xml dom.
Ajax.Open "POST", _
Props.PosseBaseURI & urlController & Props.PosseDataSourceId & "/" & _
Props.PosseDocumentObjectId & "/" & Props.PosseRecordset & _
"?sessionToken=" & Props.PosseSessionToken & _
"&PosseTraceKey=" & getTraceKey() & _
"&PosseSignIsCompleteOnDocument=" & IIf(Props.PosseSignIsCompleteOnDocument, "Y", "N") & _
"&PosseSignIsCompleteOnSource=" & IIf(Props.PosseSignIsCompleteOnSource, "Y", "N") & _
"&PosseSaveAsPDF=" & IIf(Props.PosseSaveAsPDF, "Y", "N") & _
"&PosseSaveAsRevision=" & IIf(saveRevision, "Y", "N") & _
"&" & Auth.AuthString, _
False
Ajax.setRequestHeader "Content-Type", "multipart/form-data; boundary=" & STR_BOUNDARY
Ajax.setRequestHeader "Cache-Control", "no-cache"
Ajax.setRequestHeader "Pragma", "no-cache"
Ajax.setRequestHeader "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT"
Ajax.send messageBody
setPOSSEDocument = Mid(Ajax.responseText, 2, Len(Ajax.responseText) - 2)
Exit Function
errorHandler:
showError "setPOSSEDocument"
End Function
' Show the credentials form.
Private Function showCredentialsForm()
CredentialsOK = False
CredentialsForm.Show
showCredentialsForm = CredentialsOK
End Function
' Process the document signature.
Private Sub signDocument()
On Error GoTo errorHandler:
Dim templateToken As String
Dim docToken As String
Dim section As section
Dim shape As shape
Dim result As Integer
If Len(Props.PosseBaseURI) > 0 Then
If Props.PosseIncludeUnsigned Then
' Snap a copy of the document before signing it.
' Once we snap a copy, we don't overwrite it
If Not arrayIsInitialized(UnsignedDocument) Then
UnsignedDocument = getDocumentAsByte()
End If
End If
If Not Props.PosseSignDocumentShow Then
result = 1
Else
result = getData("Sign")
End If
If result = 1 Then
' Hide the "Draft" watermark
For Each section In ActiveDocument.Sections
For Each shape In section.Headers(wdHeaderFooterPrimary).Shapes
If shape.Name Like "PowerPlusWaterMarkObject*" Or shape.Name Like "WordArt *" Then
shape.Delete
End If
Next
Next
' Save the signed and unsigned version of the document
docToken = saveDocument("Sign", Props.PosseIncludeUnsigned)
ElseIf result = 0 And Props.PosseIncludeUnsigned Then
' Because we didn't actually change anything in the document
throw away our
' Unsigned copy
Erase UnsignedDocument
End If
Else
MsgBox ("Save is not supported. Download a fresh copy of the document.")
End If
Exit Sub
errorHandler:
showError "signDocument"
End Sub
Private Function styleExists(style As String) As Boolean
On Error Resume Next
styleExists = False
styleExists = ActiveDocument.Styles(style).NameLocal = style
End Function
Private Function toByteArray(text As String) As Byte()
toByteArray = StrConv(text, vbFromUnicode)
End Function", File "CredentialsForm.frm" (Streampath: "VBA/CredentialsForm") has code: "Option Explicit
'=================================================================
'2011-01-20, Issue 1163, AVO, Consolidated from various branches.
' Click event handler for the Cancel button.
Private Sub CommandButtonCancel_Click()
CredentialsForm.Hide
End Sub
' Click event handler for the OK button.
Private Sub CommandButtonOK_Click()
If Len(UserId.text) > 0 And Len(Password.text) > 0 Then
Call PosseWordInterface.setCredentials(UserId.text, Password.text)
CredentialsForm.Hide
Else
MsgBox ("A UserId and Password must be provided.")
End If
End Sub", File "SiteSpecific.bas" (Streampath: "VBA/SiteSpecific") has code: "'This Module contains site specific code including site specific version of the FormatData method
'which is called by FormatData.
Option Explicit
Public Sub SS_FormatDocument()
'This sub must exist
at least in stub form.
'It is used to handle site specific document formatting. The blocked out code below is provided as a sample.
'Selection.WholeStory
'' Process lists
'Call ReplaceList("\<ah1\>(*)\</ah1\>", "^t\1", 2, "PosseAlphaList1", "AQ Alpha List 1", True)
'Call ReplaceList("\<a1\>(*)\</a1\>", "^t\1", 2, "PosseAlphaList1", "AQ Alpha List 1")
'' Apply styles
'Call ReplaceTextWithStyle("\<h1\>(*)\</h1\>", "\1", "Posse Heading 1")
'Call ReplaceTextWithStyle("\<aqhead\>(*)\</aqhead\>", "\1", "AQHead")
'Call ReplaceTextWithStyle("\<p1\>(*)\</p1\>", "\1", "AQ Paragraph 1")
'Call ReplaceTextWithStyle("\<p2\>(*)\</p2\>", "\1", "AQ Paragraph 2")
'Call ReplaceTextWithStyle("\<p3\>(*)\</p3\>", "\1", "AQ Paragraph 3")
'Call ReplaceTextWithStyle("\<MoEmaj\>(*)\</MoEmaj\>", "\1", "Clause Major")
'Call ReplaceTextWithStyle("\<MoEmajT\>(*)\</MoEmajT\>", "\1", "Clause Major Title")
'Call ReplaceTextWithStyle("\<MoEmin\>(*)\</MoEmin\>", "\1", "Clause Minor")
'Call ReplaceTextWithStyle("\<MoEminT\>(*)\</MoEminT\>", "\1", "Clause Minor Title")
'Call ReplaceTextWithStyle("\<MoEter\>(*)\</MoEter\>", "\1", "Clause Tertiary")
End Sub" - source
- Static Parser
- relevance
- 10/10
-
Contains embedded VBA macros (normalized)
- details
-
Normalized macro string: "http60"
Normalized macro string: "MSXML2.XMLHTTP60"
Normalized macro string: "control.id"
Normalized macro string: "http://Motobit.cz"
Normalized macro string: "dataTable.id"
Normalized macro string: "tableRow.Parent.id"
Normalized macro string: "vbCrLfC"
Normalized macro string: "RTxWihSy"
Normalized macro string: "&l;ah&g;(*)&l;/ah&g;"
Normalized macro string: "&l;a&g;(*)&l;/a&g;"
Normalized macro string: "<h>(*)</h>"
Normalized macro string: "<aqhead>(*)</aqhead>"
Normalized macro string: "<p>(*)</p>"
Normalized macro string: "<p2>(*)</p2>"
Normalized macro string: "<p3>(*)</p3>"
Normalized macro string: "<MoEmaj>(*)</MoEmaj>"
Normalized macro string: "<MoEmajT>(*)</MoEmajT>"
Normalized macro string: "<MoEmin>(*)</MoEmin>"
Normalized macro string: "<MoEminT>(*)</MoEminT>"
Normalized macro string: "<MoEter>(*)</MoEter>" - source
- File/Memory
- relevance
- 10/10
-
Creates a writable file in a temporary directory
- details
-
"WINWORD.EXE" created file "%TEMP%\msoD502.tmp"
"WINWORD.EXE" created file "%TEMP%\~DF65E633EE77F7D702.TMP"
"WINWORD.EXE" created file "%TEMP%\VBE\MSForms.exd" - source
- API Call
- relevance
- 1/10
-
Creates mutants
- details
-
"\Sessions\1\BaseNamedObjects\Global\552FFA80-3393-423d-8671-7BA046BB5906"
"\Sessions\1\BaseNamedObjects\Local\10MU_ACBPIDS_S-1-5-5-0-60938"
"\Sessions\1\BaseNamedObjects\Local\10MU_ACB10_S-1-5-5-0-60938"
"\Sessions\1\BaseNamedObjects\Local\ZonesCounterMutex"
"\Sessions\1\BaseNamedObjects\Local\ZoneAttributeCacheCounterMutex"
"\Sessions\1\BaseNamedObjects\Local\ZonesCacheCounterMutex"
"\Sessions\1\BaseNamedObjects\Local\ZonesLockedCacheCounterMutex"
"\Sessions\1\BaseNamedObjects\Global\MTX_MSO_Formal1_S-1-5-21-4162757579-3804539371-4239455898-1000"
"\Sessions\1\BaseNamedObjects\Global\MTX_MSO_AdHoc1_S-1-5-21-4162757579-3804539371-4239455898-1000"
"\Sessions\1\BaseNamedObjects\Global\MsoShellExtRegAccess_S-1-5-21-4162757579-3804539371-4239455898-1000" - source
- Created Mutant
- relevance
- 3/10
-
Loads rich edit control libraries
- details
- "WINWORD.EXE" loaded module "%COMMONPROGRAMFILES%\microsoft shared\OFFICE14\RICHED20.DLL" at 62CA0000
- source
- Loaded Module
-
Logged script engine calls
- details
-
"WINWORD.EXE" called "Forms.Form.1.CreateObject" ...
"WINWORD.EXE" called "Forms.Form.1.Enabled" ...
"WINWORD.EXE" called "Forms.Form.1.Unknown" ... - source
- API Call
- relevance
- 10/10
-
Scanning for window names
- details
-
"WINWORD.EXE" searching for class "MSOBALLOON"
"WINWORD.EXE" searching for class "MsoHelp10"
"WINWORD.EXE" searching for class "AgentAnim"
"WINWORD.EXE" searching for class "REListbox20W"
"WINWORD.EXE" searching for class "OfficeTooltip"
"WINWORD.EXE" searching for class "MsoCommandBarPopup"
"WINWORD.EXE" searching for class "NetUICtrlNotifySink"
"WINWORD.EXE" searching for class "mspim_wnd32" - source
- API Call
- relevance
- 10/10
-
Contains embedded VBA macros
-
Installation/Persistance
-
Dropped files
- details
-
"index.dat" has type "data"
"msoD502.tmp" has type "GIF image data version 89a 15 x 15"
"2914 W 29th - sewer and water locations.docm (2).LNK" has type "MS Windows shortcut Item id list present Points to a file or directory Has Relative path Archive ctime=Thu Feb 9 15:24:21 2017 mtime=Thu Feb 9 15:24:21 2017 atime=Thu Feb 9 15:26:00 2017 length=601143 window=hide"
"~WRD0001.tmp" has type "Microsoft Word 2007+"
"~WRS{E9B4E7FC-80A1-4C85-BA7D-F12B1E58F24F}.tmp" has type "FoxPro FPT blocks size 0 next free block index 218103808 1st used item "\375""
"MSForms.exd" has type "data"
"ExcludeDictionaryEN1009.lex" has type "Little-endian UTF-16 Unicode text with no line terminators"
"~$14 W 29th - sewer and water locations.docm.doc" has type "data"
"2914 W 29th - sewer and water locations.docm.LNK" has type "MS Windows shortcut Item id list present Points to a file or directory Has Relative path Archive ctime=Thu Feb 9 15:24:21 2017 mtime=Thu Feb 9 15:24:21 2017 atime=Thu Feb 9 15:26:00 2017 length=601143 window=hide"
"~WRS{C4AB1590-AE88-421E-9331-7778A33004BC}.tmp" has type "data" - source
- Binary File
- relevance
- 3/10
-
Opens the MountPointManager (often used to detect additional infection locations)
- details
- "WINWORD.EXE" opened "MountPointManager"
- source
- API Call
- relevance
- 5/10
-
Touches files in the Windows directory
- details
-
"WINWORD.EXE" touched file "%WINDIR%\Globalization\Sorting\sortdefault.nls"
"WINWORD.EXE" touched file "%WINDIR%\Fonts\staticcache.dat"
"WINWORD.EXE" touched file "%WINDIR%\Microsoft.NET\Framework\v1.0.3705\clr.dll"
"WINWORD.EXE" touched file "%WINDIR%\Microsoft.NET\Framework\v1.0.3705\mscorwks.dll"
"WINWORD.EXE" touched file "%WINDIR%\Microsoft.NET\Framework\v1.1.4322\clr.dll"
"WINWORD.EXE" touched file "%WINDIR%\Microsoft.NET\Framework\v1.1.4322\mscorwks.dll"
"WINWORD.EXE" touched file "%WINDIR%\Microsoft.NET\Framework\v2.0.50727\clr.dll"
"WINWORD.EXE" touched file "%WINDIR%\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll"
"WINWORD.EXE" touched file "%WINDIR%\Microsoft.NET\Framework\v4.0.30319\clr.dll"
"WINWORD.EXE" touched file "%LOCALAPPDATA%\Microsoft\Windows\Caches"
"WINWORD.EXE" touched file "%LOCALAPPDATA%\Microsoft\Windows\Caches\cversions.1.db"
"WINWORD.EXE" touched file "%LOCALAPPDATA%\Microsoft\Windows\Caches\{AFBF9F1A-8EE8-4C77-AF34-C647E37CA0D9}.1.ver0x0000000000000007.db"
"WINWORD.EXE" touched file "%WINDIR%\system32\rsaenh.dll"
"WINWORD.EXE" touched file "%WINDIR%\system32\en-US\KERNELBASE.dll.mui"
"WINWORD.EXE" touched file "%LOCALAPPDATA%\Microsoft\Windows\Temporary Internet Files\Content.Word\~WRS{E9B4E7FC-80A1-4C85-BA7D-F12B1E58F24F}.tmp"
"WINWORD.EXE" touched file "%WINDIR%\system32\en-US\MSCTF.dll.mui"
"WINWORD.EXE" touched file "%LOCALAPPDATA%\Microsoft\Windows\Temporary Internet Files\Content.Word\~WRF{A3728F79-E993-405E-872D-E576AD7A5EF2}.tmp"
"WINWORD.EXE" touched file "%LOCALAPPDATA%\Microsoft\Windows\Temporary Internet Files\Content.Word\~WRS{F5B54F6D-A7D2-445E-9947-F218DF8BF62F}.tmp" - source
- API Call
- relevance
- 7/10
-
Dropped files
-
Network Related
-
Found potential URL in binary/memory
- details
-
Heuristic match: "control.id"
Pattern match: "http://Motobit.cz"
Heuristic match: "dataTable.id"
Heuristic match: "tableRow.Parent.id"
Heuristic match: "6Gp%+t)Rx9p.MA"
Heuristic match: "S!u]!SEN]:w=QG3 -+d.DZ"
Heuristic match: "O}~Xa,X_;{7[|Oei#f'J3ye*Ru%lN^_|.cF"
Pattern match: "eS.kyY/5~$]'!p#m{BsY1l2|6_|:ed4XE'JHH"
Pattern match: "W..word/media/image2.pngPNG"
Heuristic match: "b:J?^_10(.?m-n=W1bDv&>-Z>uO[hHlpq5sL.hk"
Heuristic match: "PK^pzf49=2}a +Tata!b8.#J|YUg.pk"
Heuristic match: "\;njs=ZLiJ!G)w&CyK.GW"
Pattern match: "y.zj/KKu^6]V?[t'}X7:|NkGIwr"
Pattern match: "h.aS/I\U{Bui{g'qD/K}?.Q{x6nWo4="
Pattern match: "W..word/media/image2.pngPK-!word/vbaProject.binPK-" - source
- File/Memory
- relevance
- 10/10
-
Found potential URL in binary/memory
-
System Security
-
Hooks API calls
- details
-
"VariantClear@OLEAUT32.DLL" in "WINWORD.EXE"
"SysFreeString@OLEAUT32.DLL" in "WINWORD.EXE"
"OleLoadFromStream@OLE32.DLL" in "WINWORD.EXE"
"VariantChangeType@OLEAUT32.DLL" in "WINWORD.EXE"
"SysAllocStringByteLen@OLEAUT32.DLL" in "WINWORD.EXE" - source
- Hook Detection
- relevance
- 10/10
-
Queries sensitive IE security settings
- details
- "WINWORD.EXE" (Path: "HKCU\SOFTWARE\MICROSOFT\INTERNET EXPLORER\SECURITY"; Key: "DISABLESECURITYSETTINGSCHECK")
- source
- Registry Access
- relevance
- 8/10
-
Hooks API calls
-
Unusual Characteristics
-
Installs hooks/patches the running process
- details
-
"WINWORD.EXE" wrote bytes "c4cade7580bbde7552bade759fbbde7508bbde7546cede756138df75de2fdf75d0d9de75000000001779ef764f91ef767f6fef76f4f7ef7611f7ef76f283ef76857eef7600000000" to virtual address "0x6EC71000" (part of module "MSIMG32.DLL")
"WINWORD.EXE" wrote bytes "00000000" to virtual address "0x62C6BE64" (part of module "WPFT532.CNV")
"WINWORD.EXE" wrote bytes "000000000000000000000000" to virtual address "0x003363B6"
"WINWORD.EXE" wrote bytes "c7af2639" to virtual address "0x6A11CA70" (part of module "GFX.DLL")
"WINWORD.EXE" wrote bytes "bafc9f2a00b98b7b8562ffe1" to virtual address "0x0033637A"
"WINWORD.EXE" wrote bytes "f300f300" to virtual address "0x62C763DC" (part of module "WPFT532.CNV")
"WINWORD.EXE" wrote bytes "00000000" to virtual address "0x6EC41524" (part of module "FM20ENU.DLL")
"WINWORD.EXE" wrote bytes "00000000" to virtual address "0x6EC3BE64" (part of module "SENDTOONENOTEUI.DLL")
"WINWORD.EXE" wrote bytes "809b2639" to virtual address "0x68DE78E4" (part of module "OART.DLL")
"WINWORD.EXE" wrote bytes "00072139" to virtual address "0x6A49F530" (part of module "WWLIB.DLL")
"WINWORD.EXE" wrote bytes "d9270539" to virtual address "0x67DE0BA8" (part of module "MSO.DLL")
"WINWORD.EXE" wrote bytes "e2d87939" to virtual address "0x62CE9904" (part of module "RICHED20.DLL")
"WINWORD.EXE" wrote bytes "e99e48d9f1" to virtual address "0x75DF3D01" ("SetUnhandledExceptionFilter@KERNEL32.DLL")
"WINWORD.EXE" wrote bytes "00000000" to virtual address "0x62C67FA4" (part of module "WPFT532.CNV")
"WINWORD.EXE" wrote bytes "e936556bf0" to virtual address "0x77513EAE" ("VariantClear@OLEAUT32.DLL")
"WINWORD.EXE" wrote bytes "00668985" to virtual address "0x62C27FA4" (part of module "USP10.DLL")
"WINWORD.EXE" wrote bytes "badc6b5605b98b7b8562ffe1" to virtual address "0x003363A2"
"WINWORD.EXE" wrote bytes "00000000" to virtual address "0x6EC416CC" (part of module "FM20ENU.DLL")
"WINWORD.EXE" wrote bytes "000043000000000000000000" to virtual address "0x003363DE"
"WINWORD.EXE" wrote bytes "e99a546af0" to virtual address "0x77513E59" ("SysFreeString@OLEAUT32.DLL") - source
- Hook Detection
- relevance
- 10/10
-
Reads information about supported languages
- details
-
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000401")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "0000040D")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "0000041E")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "0000042A")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000439")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000420")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000429")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000409")
"WINWORD.EXE" (Path: "HKCU\CONTROL PANEL\INTERNATIONAL"; Key: "NUMSHAPE")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000402")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000403")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000404")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000405")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000406")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000407")
"WINWORD.EXE" (Path: "HKLM\SYSTEM\CONTROLSET001\CONTROL\NLS\LOCALE"; Key: "00000408") - source
- Registry Access
- relevance
- 3/10
-
Installs hooks/patches the running process
File Details
2914 W 29th - sewer and water locations.docm
- Filename
- 2914 W 29th - sewer and water locations.docm
- Size
- 587KiB (601143 bytes)
- Type
- docx office
- Description
- Microsoft Word 2007+
- Architecture
- WINDOWS
- SHA256
- 3c77345e0105c68a776920af8b2da3a17e3c6cc4276cf0c9891f83d554f625d7
- MD5
- fc06e6e2a336de099ee6f042c10a9ca0
- SHA1
- 7414c1e07f49c7d1b07e9f99281a27333059d5a1
Classification (TrID)
- 59.4% (.DOCM) Word Microsoft Office Open XML Format document (with Macro)
- 36.0% (.DOCX) Word Microsoft Office Open XML Format document
- 4.5% (.ZIP) ZIP compressed archive
Screenshots
Loading content, please wait...
Hybrid Analysis
Tip: Click an analysed process below to view more details.
Analysed 1 process in total (System Resource Monitor).
- WINWORD.EXE /n "C:\2914 W 29th - sewer and water locations.docm.doc" (PID: 3160)
Network Analysis
DNS Requests
No relevant DNS requests were made.
Contacted Hosts
No relevant hosts were contacted.
HTTP Traffic
No relevant HTTP requests were made.
Extracted Strings
Extracted Files
-
Informative 10
-
-
2914 W 29th - sewer and water locations.docm.LNK
- Size
- 633B (633 bytes)
- Type
- MS Windows shortcut, Item id list present, Points to a file or directory, Has Relative path, Archive, ctime=Thu Feb 9 15:24:21 2017, mtime=Thu Feb 9 15:24:21 2017, atime=Thu Feb 9 15:26:00 2017, length=601143, window=hide
- Runtime Process
- WINWORD.EXE (PID: 3160)
- MD5
- 3e573917fb4b54d603d0c493a2102e6d
- SHA1
- d8ad39e640236d641dd32a28ecfaf23940b19be9
- SHA256
- b9c4799b035c3ac550ba51e2f9fed13b525a4aa31303485001d2fd0989e3a0af
-
index.dat
- Size
- 562B (562 bytes)
- Type
- data
- Runtime Process
- WINWORD.EXE (PID: 3160)
- MD5
- 9d2ba074ac672db82b517b931810cd77
- SHA1
- 01ded4b07aa69f484160d11bc7998e7a188cd7ce
- SHA256
- febecbdbd9cc39b8735122d1029c3ffc862ec3adfd321eff553273be204278fd
-
~WRS{C4AB1590-AE88-421E-9331-7778A33004BC}.tmp
- Size
- 31KiB (31238 bytes)
- Type
- data
- Runtime Process
- WINWORD.EXE (PID: 3160)
- MD5
- 909fe3cca5b58effa9f231800ff0e088
- SHA1
- 01bf022eeb387eb8b8da4a28d8d20aa4f8fe3ddd
- SHA256
- 990158377a2f751777aefa92f1044c08df87bfb336fa46903e6bd10bbf342b87
-
~WRS{E9B4E7FC-80A1-4C85-BA7D-F12B1E58F24F}.tmp
- Size
- 1KiB (1024 bytes)
- Type
- FoxPro FPT, blocks size 0, next free block index 218103808, 1st used item "\375"
- Runtime Process
- WINWORD.EXE (PID: 3160)
- MD5
- 5d4d94ee7e06bbb0af9584119797b23a
- SHA1
- dbb111419c704f116efa8e72471dd83e86e49677
- SHA256
- 4826c0d860af884d3343ca6460b0006a7a2ce7dbccc4d743208585d997cc5fd1
-
MSForms.exd
- Size
- 144KiB (147284 bytes)
- Type
- data
- Runtime Process
- WINWORD.EXE (PID: 3160)
- MD5
- d473ee0b8023ef4ce9a2e63507174801
- SHA1
- c74646aaac511604f3fbe950b613af3a39f9428a
- SHA256
- 1ded77b19e76d4258df33ed10850199a9341683f033d8c9f3b009f6bad798162
-
msoD502.tmp
- Size
- 663B (663 bytes)
- Type
- GIF image data, version 89a, 15 x 15
- Runtime Process
- WINWORD.EXE (PID: 3160)
- MD5
- ed3c1c40b68ba4f40db15529d5443dec
- SHA1
- 831af99bb64a04617e0a42ea898756f9e0e0bcca
- SHA256
- 039fe79b74e6d3d561e32d4af570e6ca70db6bb3718395be2bf278b9e601279a
-
~$14 W 29th - sewer and water locations.docm.doc
- Size
- 162B (162 bytes)
- Type
- data
- Runtime Process
- WINWORD.EXE (PID: 3160)
- MD5
- 3866b43eff9511c2bc7936da8fedcbb5
- SHA1
- b2c3b12d815bc138857259ef9876f4b0bc941128
- SHA256
- 869d1d66bd497d0a21729563d6555aeae5696055d2f3e8aee69c79f549dd6f6a
-
2914 W 29th - sewer and water locations.docm (2).LNK
- Size
- 633B (633 bytes)
- Type
- MS Windows shortcut, Item id list present, Points to a file or directory, Has Relative path, Archive, ctime=Thu Feb 9 15:24:21 2017, mtime=Thu Feb 9 15:24:21 2017, atime=Thu Feb 9 15:26:00 2017, length=601143, window=hide
- MD5
- 3e573917fb4b54d603d0c493a2102e6d
- SHA1
- d8ad39e640236d641dd32a28ecfaf23940b19be9
- SHA256
- b9c4799b035c3ac550ba51e2f9fed13b525a4aa31303485001d2fd0989e3a0af
-
~WRD0001.tmp
- Size
- 1MiB (1048576 bytes)
- Type
- Microsoft Word 2007+
- MD5
- 2e7e761b1c3caa32ae0176e21e04efc0
- SHA1
- 6066276fb4f70590ea75e188560b6b9b4116591b
- SHA256
- 0ce983dbc687093b1ad9ff599c20e033ba00ef3fff4d0107b4312b15159d3a68
-
ExcludeDictionaryEN1009.lex
- Size
- 2B (2 bytes)
- Type
- Little-endian UTF-16 Unicode text, with no line terminators
- MD5
- f3b25701fe362ec84616a93a45ce9998
- SHA1
- d62636d8caec13f04e28442a0a6fa1afeb024bbb
- SHA256
- b3d510ef04275ca8e698e5b3cbb0ece3949ef9252f0cdc839e9ee347409a2209
-
Notifications
-
Runtime
- Added comment to Virus Total report
- Not all sources for signature ID "api-55" are available in the report
- Not all sources for signature ID "hooks-8" are available in the report
- Not all sources for signature ID "registry-25" are available in the report
- Not all sources for signature ID "string-50" are available in the report