I have an included JScript (Server side) that I need to pass some variables to from VBScript, but my effort using the traditional methods in ASP Classic has not worked for me, I have even tried to send a querystring with the javascript include..
My VBScript Page:
<%
Dim Tomorrow, TomorrowDay, TomorrowMonth, TomorrowYear, NewTomorrow, Today, TodayMonth, TodayYear, JSONConvertAPIStatsURL
Tomorrow = DateAdd("d",1,now())
TomorrowDay = Right("0" & Day(Tomorrow), 2)
TomorrowMonth = Right("0" & Month(Tomorrow), 2)
TomorrowYear = year(Tomorrow)
NewTomorrow = TomorrowYear & "-" & TomorrowMonth & "-" & TomorrowDay
Today = now()
TodayMonth = Right("0" & Month(Today), 2)
TodayYear = year(Today)
%>
<script language="JavaScript" runat="Server" src="retrieve_convertapi_stats.asp"></script>
<%
Dim UpdateConvertAPIJSONData
Set UpdateConvertAPIJSONData = Server.CreateObject("ADODB.Connection")
UpdateConvertAPIJSONData.ConnectionString="Provider=SQLOLEDB; DATA SOURCE=RPASQL01;UID=<USERNAME>;PWD=<PASSWORD>;DATABASE=<DATABASE>"
UpdateConvertAPIJSONData.Open
Dim UpdateConvertAPIJSONDataSQL, UpdateConvertAPIJSONDataObj
UpdateConvertAPIJSONDataSQL = "UPDATE EFP_JSON SET CONVERTAPI_STATS = '" & objSrvHTTP.responseText & "' WHERE ID = 1;"
Response.Write UpdateConvertAPIJSONDataSQL
Set UpdateConvertAPIJSONDataObj = UpdateConvertAPIJSONData.Execute(UpdateConvertAPIJSONDataSQL)
UpdateConvertAPIJSONData.Close
Set UpdateConvertAPIJSONData = Nothing
Response.Write now()
%>
My JScript (retrieve_convertapi_stats.asp)
Response.CacheControl = "no-cache"
Response.Expires = -1
Response.CodePage = 65001
Response.CharSet = "UTF-8"
var objSrvHTTP;
objSrvHTTP = Server.CreateObject ("Msxml2.ServerXMLHTTP.6.0");
objSrvHTTP.open ("GET","https://api.theurl.com/user/statistic?secret=<MY_API_KEY>&startDate=<%=TodayYear%>-<%=TodayMonth%>-01&endDate=<%=NewTomorrow%>", false);
objSrvHTTP.send ();
Response.ContentType = "application/json";
How can I achive this?
You can't pass variables to the JScript, only variables created in the JScript can be accessed in the VBscript (for whatever reason this is how it is).
I recommend you create the entire process in VBScript as the functions in JScript can be done in VBScript and you won't have any problems.
<%
Dim Tomorrow, TomorrowDay, TomorrowMonth, TomorrowYear, NewTomorrow, Today, TodayMonth, TodayYear, JSONConvertAPIStatsURL
Tomorrow = DateAdd("d",1,now())
TomorrowDay = Right("0" & Day(Tomorrow), 2)
TomorrowMonth = Right("0" & Month(Tomorrow), 2)
TomorrowYear = year(Tomorrow)
NewTomorrow = TomorrowYear & "-" & TomorrowMonth & "-" & TomorrowDay
Today = now()
TodayMonth = Right("0" & Month(Today), 2)
TodayYear = year(Today)
Dim xml, url
Set xml = CreateObject("Msxml2.ServerXMLHTTP.6.0")
url = "https://api.theurl.com/user/statistic?secret=<MY_API_KEY>&startDate=" & TodayYear & "-" & TodayMonth & "-01&endDate=" & NewTomorrow
xml.open "GET", url, false
xml.setRequestHeader "Content-Type", "application/json"
xml.Send
status = trim(xml.status) ' server status
returnresponse = xml.responseText ' entire body
%>
You can pass variables to JavaScript from VB by writing in the JavaScript dynamically so that it can include the new variables.
VB (ASP) code is ececuted server side, so it will send the modified JavaScript to the user where it is later actioned in the browser, no problem.
Related
I am trying to set cookie with addheader -method in Classic Asp which is the only way of adding among other things HttpOnly and Secure -flags to cookies. All work with the below code - but there is one exception and its is the expiration date/time.
<%
Response.AddHeader "Set-Cookie", "testCookie=2000; path=/;HttpOnly;Secure;expires=" & dateAdd("d", 365, Now()) & ";samesite=Strict;HostOnly"
%>
However, it seems to be browser-related issue. In firefox I can see in the Storage tab of developer tools that expiration time is set. But in Chrome it always stays as the default which is the expiration with the end of session. This same issue is with the Edge too.
Has anyone any experience with this issue?
The expected date format is documented here. You need to produce expiration date in that manner.
In Classic ASP, you can use server-side JavaScript to produce such dates easily.
<!--#include file="HTTPDate.asp"-->
<%
Response.AddHeader "Set-Cookie", "testCookie=2000; path=/;HttpOnly;Secure;expires=" & HTTPDate(DateAdd("d", 365, Now())) & ";samesite=Strict;HostOnly"
%>
HTTPDate.asp
<script language="javascript" runat="server">
function HTTPDate(vbsDate){
return (new Date(vbsDate)).toGMTString().replace(/UTC/, "GMT");
}
</script>
Edit: Pure VBScript solution added.
<%
Function CurrentTZO()
With CreateObject("WScript.Shell")
CurrentTZO = .RegRead( _
"HKLM\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias")
End With
End Function
Function Pad(text)
Pad = Right("00" & text, 2)
End Function
Function HTTPDate(ByVal localDate)
localDate = DateAdd("n", CurrentTZO(), localDate)
' WeekdayName and MonthName functions relies on locale
' need to produce day and month name abbreviations in en-US locale
Dim locale : locale = SetLocale("en-US")
Dim out(5)
out(0) = WeekdayName(Weekday(localDate), True) & ","
out(1) = Pad(Day(localDate))
out(2) = MonthName(Month(localDate), True)
out(3) = Year(localDate)
out(4) = Join(Array(Pad(Hour(localDate)), Pad(Minute(localDate)), Pad(Second(localDate))), ":")
out(5) = "GMT"
SetLocale locale ' set original locale back
HTTPDate = Join(out, " ")
End Function
Response.AddHeader "Set-Cookie", "testCookie=2000; path=/;HttpOnly;Secure;expires=" & HTTPDate(DateAdd("d", 365, Now())) & ";samesite=Strict;HostOnly"
%>
In addition to the accepted solution of Kul-Tigin I want to add also a vbscript solution for those who are missing that too.
<%
Response.AddHeader "Set-Cookie", "testCookie=2000; path=/;HttpOnly;Secure;expires=" & (New UTC).toUTCString(500,"d") & ";samesite=Strict;HostOnly;"
Class UTC
Public Function toUTCString(ByVal offSet, ByVal offsetType)
' ***********************************
' Converts vbScript datetime format to
' Universal datetime string format:
' Tue, 16 Feb 2021 13:39:24 GMT
'************************************
Dim dt: dt = dateAdd(offsetType, offSet, UTCDate(Now()))
Dim tdParts: tdParts = Split(dt, " ")
Dim tPart: tPart = CDate(tdParts(1) & " " & tdParts(2))
Dim dPart: dPart = CDate(tdParts(0))
Dim timeTo24: timeTo24 = _
Right("0" & Hour(tPart), 2) & ":" & _
Right("0" & Minute(tPart), 2) & ":" & _
Right("0" & Second(tPart), 2)
toUTCString = WeekdayName(Weekday(dPart), True) & ", " & _
Day(dPart) & " " & _
MonthName(Month(dPart), True) & " " & _
Year(dPart) & " " & _
timeTo24 & " GMT"
End Function
Public Function UTCDate(ByVal dtDate)
If Not IsDate(dtDate) Then Err.Raise 5
dtDate = CDate(dtDate)
Dim ZoneBias: ZoneBias = TimeZoneBias()
If IsPDT(Now) <> IsPDT(dtDate) Then
ZoneBias = ZoneBias - 60
End If
UTCDate = DateAdd("n", ZoneBias, dtDate)
End Function
Private Function IsPDT(ByVal dtDate)
If Not IsDate(dtDate) Then Err.Raise 5
dtDate = CDate(dtDate)
Dim pdtLow, pdtUpr, nDaysBack
pdtLow = DateSerial(Year(dtDate), 3, 31)
pdtUpr = DateSerial(Year(dtDate), 10, 31)
pdtLow = DateAdd("h", 2, pdtLow)
pdtUpr = DateAdd("h", 2, pdtUpr)
nDaysBack = Weekday(pdtLow) - 1
If nDaysBack <> 0 Then
pdtLow = DateAdd("d", -nDaysBack, pdtLow)
End If
nDaysBack = Weekday(pdtUpr) - 1
If nDaysBack <> 0 Then
pdtUpr = DateAdd("d", -nDaysBack, pdtUpr)
End If
IsPDT = (dtDate >= pdtLow And dtDate <= pdtUpr)
End Function
Private Function TimeZoneBias()
Dim LTZone
With GetObject("winmgmts:" & _
"{impersonationLevel=impersonate}!\\.\root\cimv2")
For Each LTZone In .ExecQuery(_
"Select * From Win32_ComputerSystem")
TimeZoneBias = LTZone.CurrentTimeZone
Next
End With
TimeZoneBias = TimeZoneBias * -1
End Function
End Class
%>
I have the following code, which used to work perfectly, But now for somes reason, doesn't.
The XML I am reading is located at: https://forex.boi.org.il/currency.xml
The following code should parse the XMl and then save the USD/ILS exchange rate. As I say, it doesnt anymore, and I cant figure out whats wrong.
forexURL = "https://forex.boi.org.il/currency.xml"
getUSDRate = 0
MyRate = 0
Set xmlObj = Server.CreateObject("MSXML2.FreeThreadedDOMDocument")
xmlObj.async = False
xmlObj.setProperty "ServerHTTPRequest", True
xmlObj.Load(forexURL)
Set xmlList = xmlObj.getElementsByTagName("CURRENCY")
Set xmlObj = Nothing
x = 1
For Each xmlItem In xmlList
response.write "<p>" & xmlItem.childNodes(0).text
response.write "<p>" & xmlItem.childNodes(1).text
response.write "<p>" & xmlItem.childNodes(2).text
response.write "<p>" & xmlItem.childNodes(3).text
response.write "<p>" & xmlItem.childNodes(4).text
response.write "<p>" & xmlItem.childNodes(5).text
response.write "<p>___________________<br />" & x & "</p>"
if xmlItem.childNodes(2).text = "USD" then
MyRate = xmlItem.childNodes(4).text
exit for
end if
x = x +1
Next
Set xmlList = Nothing
I suspect (wild guess ahead) changes to the way SSL is handled on the server side as the cause of your trouble. Maybe they disabled older, more insecure ciphers in response to recent SSL bugs.
Like #John notes - when you change from MSXML2.FreeThreadedDOMDocument (which loads version MSXML2 version 3) to explicitly load the more modern version 6 (MSXML2.FreeThreadedDOMDocument.6.0) then the download of the document succeeds.
That being said I've made a few changes to your code, mostly to be more readable and make it fail visibly when the document load fails for some reason.
Note
the use of XPath
a helper function GetText() in place of blindly indexing into child nodes
the parseError check to make LoadXmlDocument fail non-silently
.
Option Explicit
Dim usdRate, x, currencies, curr
Set currencies = LoadXmlDocument("https://forex.boi.org.il/currency.xml")
usdRate = GetText(currencies, "//CURRENCY[CURRENCYCODE = 'USD']/RATE")
x = 1
For Each curr In currencies.getElementsByTagName("CURRENCY")
Response.Write "<p>" & GetText(curr, "NAME") & "</p>"
Response.Write "<p>" & GetText(curr, "UNIT") & "</p>"
Response.Write "<p>" & GetText(curr, "CURRENCYCODE") & "</p>"
Response.Write "<p>" & GetText(curr, "COUNTRY") & "</p>"
Response.Write "<p>" & GetText(curr, "RATE") & "</p>"
Response.Write "<p>" & GetText(curr, "CHANGE") & "</p>"
Response.Write "<p>___________________<br />" & x & "</p>"
x = x + 1
Next
' ----------------------------------------------------------------------
' loads an XML document from a URL and returns it
Function LoadXmlDocument(url)
Set LoadXmlDocument = CreateObject("MSXML2.FreeThreadedDOMDocument.6.0")
LoadXmlDocument.async = False
LoadXmlDocument.setProperty "ServerHTTPRequest", True
LoadXmlDocument.setProperty "SelectionLanguage", "XPath"
LoadXmlDocument.Load url
If LoadXmlDocument.parseError <> 0 Then
Err.Raise vbObjectError + 1, _
"LoadXmlDocument", _
"Cannot load " & url & " (" & LoadXmlDocument.parseError.reason & ")"
End If
End Function
' finds the first node that matches the XPath and returns its text value
Function GetText(context, xpath)
Dim node
Set node = context.selectSingleNode(xpath)
If node Is Nothing Then
GetText = vbEmpty
Else
GetText = node.text
End If
End Function
I just tried this on my machine. Try replacing
Server.CreateObject("MSXML2.FreeThreadedDOMDocument")
with
Server.CreateObject("Msxml2.DomDocument.6.0")
Edit
Server.CreateObject("MSXML2.FreeThreadedDOMDocument.6.0")
also seems to work
You can find examples of code on how to fetch weather data using PHP, Ruby, Python, ColdFusion, and jQuery here: http://www.wunderground.com/weather/api/d/docs?d=resources/code-samples, I was wondering if there was an equivalent of this regarding VBScript that someone was aware of.
I have a very limited understanding of VB, no less VBS, but I found this code online which seems like it might work:
Option Explicit
'On Error Resume Next
Dim objXML, strXMLFile, weatherFor, weatherCondition, currTemp, highTemp, lowTemp
strXMLFile = "C:\Temp\test.xml"
Set objXML = CreateObject("Microsoft.XMLDOM")
objXML.async = "False"
objXML.load(strXMLFile)
weatherFor = objXML.getElementsByTagName("yweather:location").item(0).attributes.getNamedItem("city").value
weatherCondition = objXML.getElementsByTagName("yweather:condition").item(0).attributes.getNamedItem("text").value
currTemp = objXML.getElementsByTagName("yweather:condition").item(0).attributes.getNamedItem("temp").value
highTemp = objXML.getElementsByTagName("yweather:forecast").item(0).attributes.getNamedItem("high").value
lowTemp = objXML.getElementsByTagName("yweather:forecast").item(0).attributes.getNamedItem("low").value
WScript.Echo weatherFor
WScript.Echo weatherCondition
WScript.Echo currTemp
WScript.Echo highTemp
WScript.Echo lowTemp
But when I try to execute it I get the error: Object required: getElementsByTagName(...).item(...)
I've looked it up and this is the problem: http://www.computerperformance.co.uk/Logon/code/code_800A01A8.htm, but I'm not sure what to make of it.
Does someone know how to solve this error code, or a better way to do this altogether? Thank you very much in advance.
[Edit:]
Here's some working code:
Dim WeatherRSS
WeatherRSS = "http://weather.yahooapis.com/forecastrss?p=CAXX0773&u=c"
Dim WinHttpReq, XMLData, objXML, weatherCity, weatherCondition, currTemp, highTemp, lowTemp
Dim Response, Talker
Set WinHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")
WinHttpReq.Open "GET", WeatherRSS, False
WinHttpReq.Send
If (WinHttpReq.Status = 200) Then
XMLData = WinHttpReq.ResponseText
Set objXML = CreateObject("Microsoft.XMLDOM")
objXML.async = "False"
objXML.loadXML(XMLData)
weatherCity = objXML.getElementsByTagName("yweather:location").item(0).attributes.getNamedItem("city").value
weatherCondition = objXML.getElementsByTagName("yweather:condition").item(0).attributes.getNamedItem("text").value
currTemp = objXML.getElementsByTagName("yweather:condition").item(0).attributes.getNamedItem("temp").value
highTemp = objXML.getElementsByTagName("yweather:forecast").item(0).attributes.getNamedItem("high").value
lowTemp = objXML.getElementsByTagName("yweather:forecast").item(0).attributes.getNamedItem("low").value
weather = weatherCondition & " " & currTemp & " " & highTemp & " " &
lowTemp & " " + weatherCity & "."
else weather = "Sorry, I can't predict the weather today."
end if
msgbox(weather)
I'm trying to create an HTA To Do List saving locally to a text file. Every time you press submit button generates a new entry that display inside hta body and it's being saved inside the text file. I want to develop this furthermore :
delete an entry and update body/text file
modify an entry and update body/text file
put new entry on top
Any suggestions?
<html>
<head>
<HTA:APPLICATION SINGLEINSTANCE="yes" APPLICATIONNAME="To Do List">
</head>
<SCRIPT Language="VBScript">
Sub Window_OnLoad
ReadBlog
End Sub
Sub SaveData
strDel1="<"
strDel2=">"
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists("C:\Test.txt") Then
Set objFile = objFSO.OpenTextFile("C:\Test.txt", 8)
strLine = strDel1 & Time & vbTab & Date & vbTab & Title.Value & vbTab & Message.Value & strDel2
objFile.WriteLine strLine
objFile.Close
Else
Set objFile = objFSO.CreateTextFile("C:\Test.txt")
strLine = strDel1 & Time & vbTab & Date & vbTab & Title.Value & vbTab & Message.Value & strDel2
objFile.WriteLine strLine
objFile.Close
End If
ReadBlog
ClearText
End Sub
Sub ReadBlog
Const ForReading = 1, ForWriting = 2
dim sampletext, objRegExp, SearchPattern, ReplacePattern, matches
Dim objFSO
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Test.txt", ForReading)
Do Until objFile.AtEndOfStream
sampletext = objFile.ReadAll
SearchPattern = "<"
SearchPattern = SearchPattern & "(.*?)([\s\S]*?)"
SearchPattern = SearchPattern & ">"
Set objRegExp = New RegExp
objRegExp.Pattern = searchpattern ' apply the search pattern
objRegExp.Global = True ' match all instances if the serach pattern
objRegExp.IgnoreCase = True ' ignore case
Set matches = objRegExp.execute(sampletext)
If matches.Count > 0 Then ' there was at least one match to the search pattern
i=0
For Each match in matches
arrEntry = Split(Split(match.Value, "<")(1), ">")(0)
arrFields = Split(arrEntry, vbTab)
strTime = arrFields(0)
strDate = arrFields(1)
strTitle = arrFields(2)
strMessage = arrFields(3)
strHTML = strHTML & "<p>" & strTime & "</p>"
strHTML = strHTML & "<p>" & strDate & "</p>"
strHTML = strHTML & "<p>" & strTitle & "</p>"
strHTML = strHTML & "<p>" & strMessage & "</p>"
strHTML = strHTML & "<input type='button' name='Delete' value='Delete' >"& i &"<p>"
i=i+1
Next
Else ' there were no matches found
MsgBox objRegExp.Pattern & "was not found in the string"
End If
Loop
DataArea.InnerHTML = strHTML
Set objRegExp = Nothing
Set objFSO = Nothing
End Sub
Sub ClearText
Title.Value = ""
Message.Value = ""
End Sub
</SCRIPT>
<body>
<input type="text" name="Title" size="101"><p>
<textarea rows="10" cols="76" type="text" name="Message" size="25"></textarea><p>
<input type="button" value="Submit" onClick="SaveData">
<p><div id="DataArea"></div></p>
</body>
</html>
Are you particularly tied to using text files? If you used a database (such as access) you could do this quite easily (you don't have to have access installed to use an access database with an HTA either). And it would open up some other possibilities.
Incidentally, I also notice you're doing this:
strHTML = strHTML & "<p>" & strTime & "</p>"
strHTML = strHTML & "<p>" & strDate & "</p>"
strHTML = strHTML & "<p>" & strTitle & "</p>"
strHTML = strHTML & "<p>" & strMessage & "</p>"
Not a big thing, but concatenating the strings like that isn't great for performance. You'd be better off writing it all to the variable at the same time, otherwise it has to keep writing the variable to memory over and over again.
If you want to read a file with HTA you can easily do it in javaScript. Since the context changes IE allws you to directly read file on the computer or the network to wich the computer is linked to. In order to do so, you need to access the File System Object (FSO)
Full Documentation on FSO
If you are still looking to access a database you need to use the ADODB.Connection. That will allow you to connect to database localy or remotely. Altought there is not much documentation on the subject we did it at my work place. With a little imagination you can figure out how to fix it.
Documentation on the ADODB.Connnect
In this documentation the example are in VB but you can write them in JS as well.
I want to write a VBS macro to auto generate an email in outlook and attach a word document. I currently have a macro that does this for excel, but I can't get it to work for Word. I can't figure out for the life of me what my "FName= " should be. Any suggestions or help would be greatly appreciated. Here is what I have:
Sub AutoEmail()
On Error GoTo Cancel
Dim Resp As Integer
Resp = MsgBox(prompt:=vbCr & "Yes = Review Email" & vbCr & "No = Immediately Send" & vbCr & "Cancel = Cancel" & vbCr, _
Title:="Review email before sending?", _
Buttons:=3 + 32)
Select Case Resp
'Yes was clicked, user wants to review email first
Case Is = 6
Dim myOutlook As Object
Dim myMailItem As Object
Set otlApp = CreateObject("Outlook.Application")
Set otlNewMail = otlApp.CreateItem(olMailItem)
FName = ActiveWord & "\" & ActiveWord.Name
With otlNewMail
.To = ""
.CC = ""
.Subject = ""
.Body = "Good Morning," & vbCr & vbCr & "" & Format(Date, "MM/DD") & "."
.Attachments.Add FName
.Display
End With
Set otlNewMail = Nothing
Set otlApp = Nothing
Set otlAttach = Nothing
Set otlMess = Nothing
Set otlNSpace = Nothing
'If no is clicked
Case Is = 7
Dim myOutlok As Object
Dim myMailItm As Object
Set otlApp = CreateObject("Outlook.Application")
Set otlNewMail = otlApp.CreateItem(olMailItem)
FName = ActiveWorkbook.Path & "\" & ActiveWorkbook.Name
With otlNewMail
.To = ""
.CC = ""
.Subject = ""
.Body = "Good Morning," & vbCr & vbCr & " " & Format(Date, "MM/DD") & "."
.Attachments.Add FName
.Send
'.Display
'Application.Wait (Now + TimeValue("0:00:01"))
'Application.SendKeys "%s"
End With
'otlApp.Quit
Set otlNewMail = Nothing
Set otlApp = Nothing
Set otlAttach = Nothing
Set otlMess = Nothing
Set otlNSpace = Nothing
'If Cancel is clicked
Case Is = 2
Cancel:
MsgBox prompt:="No Email has been sent.", _
Title:="EMAIL CANCELLED", _
Buttons:=64
End Select
End Sub
May it is a bit late, but I want to solve it for future use.
You want to have the active document as your file name (FName).
FName = Application.ActiveDocument.Path + "\" + Application.ActiveDocument.Name
' .Path returns only the Path where the file is saved without the file name like "C:\Test"
' .Name returns only the Name of the file, including the current type like "example.doc"
' Backslash is needed because of the missing backslash from .Path
otlNewMail.Attachements.Add FName
May you also want to save your current document before sending it via outlook, otherwise you will send the document without the changes made.
Function SaveDoc()
ActiveDocument.Save
End Function
I hope that this will help others, because the code from the question helped me a lot while scripting a similar script.