FileExists Returning False - vbscript

I'm creating a Classic ASP page and trying to determine if a .jpg is on my web server. If the image exists then I want to use it, but if the image does not exist, I display a generic image. This is always false. Any ideas?
<%dim fs
strFilePath =("http:/example.com/photos/" & PersonID & ".jpg")
set fs=Server.CreateObject("Scripting.FileSystemObject")
if fs.FileExists(strFilePath) then
response.write "<img src='../photos/"& PersonID &".jpg'"&">"
else%>
<img src="http://exmaple.com/images/nophoto.jpg">
<%end if
set fs=nothing%>

The Scripting.FileSystemObject only supports accessing files from the file system and has no way to determine whether a file exists at a particular external URL. If the URL is within the current Web Application you can use;
Server.MapPath(relative_path)
which if passed a relative server path i.e "/photos" will return the physical path to the file on the server, which you can then test with fs.FileExists().
But if the URL is external you still have options. By using a server-side XHR request to the URL and based on the response, determine it's existence. We can also make this more efficient by only asking whether it is there and not returning the content, which we can do by using a HEAD request.
Here is an example of a possible implementation;
<%
Function CheckFileExists(url)
Dim xhr: Set xhr = Server.CreateObject("WinHttp.WinHttpRequest.5.1")
With xhr
Call .Open("HEAD", url)
Call .Send()
CheckFileExists = (.Status = 200)
End With
End Function
If CheckFileExists("https://cdn.sstatic.net/Img/unified/sprites.svg?v=fcc0ea44ba27") Then
Call Response.Write("File Exists")
Else
Call Response.Write("File Doesn't Exist")
End If
%>
Output:
File Exists
Useful Links
Does File Exist? ASP Classic (Explains use of Server.MapPath())

Related

VBScript: Download JSON File From Webpage and Read Contents to Variable

I'm trying to write a VB script that will log into a secure website and download a series of reports.
The following gets me into the website, but after login the whole site is written in javascript.
Dim oIE
Set oIE = CreateObject("InternetExplorer.Application")
With oIE
.Visible = True
.Navigate SecureWebsite
Do While .Busy Or Not .readyState = 4: WScript.Sleep 100: Loop
Do Until .document.readyState = "complete": WScript.Sleep 100: Loop
Do While TypeName(.document.getElementById("username")) = "Null": WScript.Sleep 100: Loop
End With
Set Helem = oIE.document.getElementByID("username")
Helem.Value = "myusername"
Set Helem = oIE.document.getElementByID("password")
Helem.Value = "mypassword"
Call oIE.Document.all.loginForm.submit
I've found a link that I can use with parameters to search for the reports I need. When I follow the link, Internet Explorer returns a JSON file that I can open/download. The JSON file contains a Report ID that I can use as a parameter in another link to download the file that I need.
Is there any way using the InternetExplorer object to read the text contents of the JSON file into a variable so that I can parse the Report ID out of it? All the examples I've found use the MSXML2.XMLHTTP object, but that disconnects it from the sign-on I've achieved in the InternetExplorer object.
I ended up doing this in C#. The website had redirects and SSO so I couldn't get a direct WebClient Get/Post, but I compromised by logging in using a WebBrowser object and then passing the cookies to a HttpWebRequest object, per this excellent guide:
https://www.codeproject.com/Tips/659004/Download-of-file-with-open-save-dialog-box

SSRS External Images with Dynamic File Extensions

I have a report that needs to show images from a Windows folder on the server, which is working (see here ). Now, I am wondering how to get the report to pull images of differing file types, like jpg & tif. (I am using png by default). Is there a relatively easy way to do this? The image names with file extension are not in the SQL database.
EDIT: I entered this in the Custom Code block, from Daniel's help below.
Public Function GetImage(ByRef Filename As String) As String
' Full image path used for testing if it exists
Dim ImagePath As String
ImagePath = "\\GVSSERVER1\GVSServerD\Acclamare_Images\" + Filename
' Test to see if the file exists as a gif
Try
If System.IO.File.Exists(ImagePath + ".png")
Return "file://" + ImagePath + ".png"
ElseIf System.IO.File.Exists(ImagePath + ".jpg")
Else Return "file://" + ImagePath + ".jpg"
End If
Catch ex As Exception
Return "Hit an Error"
End Try
Return "Hit the end"
End Function
When I run the report, it fetches the .jpg extension even though the image file is a png, and there isn't a jpg file for that item. Any idea on how to correct that?
EDIT 2: I wasn't having success with the updated custom code, but I could have been missing something, as I'm no expert with custom code. I found this question (see here) which is for a function. I tried it and it works, except for some reason .tif files don't display on the report. I installed Microsoft Picture Manager (from the Sharepoint exe download), but it still doesn't display the .tif files.
The good news is that this is definetely possible, however it takes a bit of custom code and server side tweaking to get ready.
General Idea: Create a code behind function that takes the name of our image and then does file existence tests to determine which file extension type actually exists on the network share.
If you right-click outside of the report area and go to properties, you will see the custom code window where you can paste the following function code.
Custom Code:
Public Function GetImage(ByRef Filename As String) As String
' Full image path used for testing if the image exists
Dim ImagePath As String
ImagePath = "\\EM-SSRS\ImageTest\" + Filename
' Test to see if the file exists as a gif
If System.IO.File.Exists(ImagePath + ".gif") THEN
Return "file://" + ImagePath + ".gif"
ElseIf System.IO.File.Exists(ImagePath + ".png") THEN
Return "file://" + ImagePath + ".png"
ElseIf System.IO.File.Exists(ImagePath + ".jpg") THEN
Return "file://" + ImagePath + ".jpg"
ElseIf System.IO.File.Exists(ImagePath + ".jpeg") THEN
Return "file://" + ImagePath + ".jpeg"
End If
Return "No Image Exists"
End Function
You will have to edit the ImagePath variable to contain the network share path for your scenario or even add another parameter to the function to make it more generic if you wish.
Once the code function is created, I would advise creating a dummy textbox expression on the report and using the following value:
=Code.GetImage("Filenmame")
Which will allow you to view the output of the function and tweak things as needed. Note that the "file:// ... " syntax may not work from within report builder or visual studio and may have to be deployed to a report server for testing.
Of course, once it looks like the function is working, add the image, make sure to set the source to external and use the same expression as for the textbox.
Server Side Changes
Upon further testing on my own environment, I've had to make two additional changes to get this to work:
Ensure that the unattended execution account is set to a domain account that has permission to the file share
Edit the SSRS config in the rssrvpolicy.config file to trust custom code and allow the execution of the File.Exists function by specifying "FullTrust"
<CodeGroup
class="UnionCodeGroup"
version="1'
PermissionSetName="FullTrust"
Name="Report_Expressions_Default_Permissions"
Description="This code group grants default permissions for code in report expressions and code element."
...
</CodeGroup>
I did restart the SSRS service after making these changes (I assume that's required, but did it as a precaution)
Note that I am not an SSRS server admin and someone else may be able to add some additional information about the custom policy change. Glancing through the MS documentation, there is a recommendation about using custom assemblies instead so take this part with a grain of salt.

VBScript runtime error '800a01a8', Object required: '' when using WScript.Quit

I am putting the final pieces into a VBScript page and one thing I want to handle is if the variable being passed in via the URL is empty. If that is the case, I want the page to stop running and show a 'must log in' message.
I have the following code in place:
<%
If (Request.QueryString("nn") = "") Then
Response.Write "<p>You must be logged in to view content. <a href='http://URL/login?ReturnUrl=/interests'>Click here</a> to log in.</p>"
WScript.Quit
End If
%>
The error throws on the line WScript.Quit. Any ideas?
WScript.Quit, as the name implies, is part of the Windows Script Host. You appear to be using VBScript within a different host: ASP. If you need to stop processing an ASP page, just end the server's response by using:
Response.End

Creating a view and agent in multiple databases

The problem I am encountering is that some of the messages are not accessible by the user ID file, I would like to skip these files instead of the agent crashing out. The error message received is as follows:
Using the view approach if this happened I was able to delete the document temporarily and re-run the agent but if there is a way to skip documents it would be a great help.
Thanks for the help guys.
Ok I have amended the code to a point where I am almost comfortable with it.
Sub Initialize
Dim s As New notessession
Dim db As notesdatabase
Dim view As notesview
Dim doc As notesdocument
Dim nextdoc As notesdocument
Set db = s.currentdatabase
If view Is Nothing Then
Set view = db.CreateView("Encrypted",{Encrypt="1"})
End If
Set doc = view.getfirstdocument
On Error Goto ErrorHandler
While Not doc Is Nothing
nextDocument:
Set nextdoc = view.getnextdocument(doc)
'The below loop is mandatory to ensure that all $File entries are unecrypted
Forall i In doc.items
If i.isencrypted Then
i.isencrypted=False
End If
End Forall
'Must have at least 1 field encrypted in order to call Encrypt method
Dim temp As New NotesItem(doc,"tempjunk","temp")
temp.IsEncrypted=True
Call doc.encrypt
Call doc.save(True, False)
'This portion can now remove the fields relative to encrypting the
'single token encrypted field.
Call doc.removeitem("$Seal")
Call doc.removeitem("$SealData")
Call doc.removeitem("SecretEncryptionKeys")
Call doc.removeitem("Encrypt")
Call doc.removeItem("tempjunk")
Call doc.save(True, False)
Set doc = nextdoc
Wend
Exit Sub
ErrorHandler:
On Error Resume nextDocument
Exit Sub
End Sub
The error handling is not playing nice;
On Error Resume nextDocument is showing up as an error.
I have tried suppressing all of the error warnings which seems to attempt to strip the encryption but I think they body of the messages is being destroyed as a result.
It is no problem to create an agent in a container database and let that agent access documents in all "target" databases and modify them accordingly - No need to copy that agent to all databases.
Only restriction: If the databases are on another server, then on the server security tab of the target server you have to enter the server with the container database as trusted server.
AND: If your agent runs longer than the allowed maximum run time for agents on the server, then it will be killed prematurely.
There is no need to create views in the target databases, you can use NotesDatabase.Search() to get the corresponding documents in the databases...
You can create views by copying them from another database. Say you create a view "Encrypted" in your db with the agent.
Then add a piece of code to get a handle of this view as a NotesDocument:
Dim dbThis As NotesDatabase
Dim viewTemplate As NotesView
Dim docView As NotesDocument
Set dbThis = s.currentDatabase
Set viewTemplate = dbThis.getView("Encrypted")
Set docView = dbThis.Getdocumentbyunid(viewTemplate.Universalid)
In the agent loop, test if view Encrypted exists, if not copy the "view template":
Set view = db.getview("Encrypted")
If view Is Nothing Then
Call docView.Copytodatabase(db)
Set view = db.getview("Encrypted")
End If
Finally, if you insist, a similar procedure might be used to copy the agent to all databases, but for me the idea of running the agent in one db sounds better.
Edited: In the view of full disclosure - of course you can create a view (I guess that was the original question).
If view Is Nothing Then
Set view = db.Createview("Encrypted", {Encrypt="1"})
End If
Or do one-shot dbSearch suggested by Torsten, with a good re-mark of Richard - if you intend to run your code several times - say if encrypted documents might get created again or re-encrypted, rather go for the view.
My method is a bit old fashioned (pre-dates availability of createView) and works well if you need more than selection formula, so you can pre-build a complicated view for re-use.
Performance-wise: whatever method you will choose either creating view using createView or copying from other db or doing dbSearch there is going to be a certain slow-down while the view gets built or dbSearch executes. Karl-Henry's approach will avoid this search/view build, but will be relatively slow if there are not many encrypted documents.
Whichever method you choose - here is a small tip to boost performance. Make your loops like this to release memory as you go; for example, assuming Karl-Henry's approach:
Dim doc1 as NotesDocument
Set doc = col.GetFirstDocument()
Do Until doc Is Nothing
Set doc1 = col.GetNextDocument(doc)
formname = doc.GetItemValue("Form")(0)
If IsElement(exclude(formname))=False Then
Call RemoveEncryption(doc) '*** Your function to remove encryption
End If
' releasing memory when processing thousands of documents improves performance and avoids crashes
Delete doc
Set doc = doc1
Loop
Now again, as you are talking only about migration (so one shot) of 20+ databases, the speed or implementation details should not be that critical.
If you have to process all (or almost all) documents in each database, you can use db.AllDocuments. It is more efficient than using db.Search() with an #All formula.
If you want to exclude certain documents, perhaps based on the form name, I would build a list of forms to exclude, and then use IsElement to check each document being processed against that list.
Dim exclude List As Boolean
exclude("FormA")=True
exclude("FormB")=True
Set col = db.AllDocuments
Set doc = col.GetFirstDocument()
Do Until doc Is Nothing
formname = doc.GetItemValue("Form")(0)
If IsElement(exclude(formname))=False Then
Call RemoveEncryption(doc) '*** Your function to remove encryption
End If
Set doc = col.GetNextDocument(doc)
Loop
Something like that. By the way, you can create the list as any data type. I just choose Boolean as it is a small data type, and that it makes the code easier to read. The IsElement() function just check if the element exists, it does not use the value you set.
You would wrap the code above in a function and call it once per database.
Appended answer, based on additional info in original question:
That should not be hard, just add error handling to your code.
Before you start to loop throung the document:
On Error Goto errHandler
Before you get the next document in the loop:
nextDocument:
At the end of your code:
Exit Sub
errHandler:
Resume nextDocument
End Sub
Try that.

Send Email Using Classic ASP with an Embeded Image

i am making NewsLetter using the wysiwyg Editor.. it allows me to upload the Image Path
and Image Path is stored in the Upload Directory..
Not When i retrieve that Image using it works in website..
the editor's value is stored in database
example
<br> hi
<img src="upload/acb.gif">
<br>
Hello
i am sending Email and the detail of this email is received from database
and this detail is sent to visitor
he is gettion all text value but not able to see Image
so suggest me what to do..?
If you are sending emails using CDOSYS.Message, you can easily send a complete web page with embedded images using the Message.CreateMHTMLBody(url) method.
Dim Message
Set Message = CreateObject("CDOSYS.Message")
Message.From = "from#email.org"
Message.To = "to#email.org"
Message.CreateMTHMLBody "http://yourserver.org/email.html"
Message.Send()
I recently cleaned up some code I had lying around to do this and slapped it online as a "Gist" on github; hope it still helps someone!
Sending embedded images with CDOSYS
This solution uses CDO (CDOSYS / CDO.Message), with "AddAttachment", and manually controlling the properties of the attachments to make them usable from within the email HTML and to avoid them appearing as separately-downloadable attachments in an email client.
The usage is very simple, just reference the images by a local path (on the computer the code is running on) in the HTML of the message, eg:
Some Image: <img src="<EMBEDDEDIMAGE:C:\test.jpeg>" />
The code will pick up the filename, add the file as an attachment to the message, and replace the relevant part of the message HTML with the internal reference to that attachment.
You would have to add site url to img source
<img src="http://www.sitename.com/upload/acb.gif"> as the user is not accessing your site from his mailbox.
For this you can set "http://www.sitename.com/" as a key in web.config and use in your mails.
This will resolve your problem for sure. Happy coding !!!!!!!!!!!!!
You would use AddRelatedBodyPart:
Embed Usage
Create Array and Pass it in "SendMail" Function as Parameter
Use in Email Body e.g.
Dim arrRelatedBodyPart(1)
arrRelatedBodyPart(0) = Server.MapPath(".") & "/images/barcode/bar_blk.gif"
arrRelatedBodyPart(1) = Server.MapPath(".") & "/images/barcode/bar_wht.gif"
Example
For i = 0 To UBound(arrRelatedBodyPart)
Dim strPathAndFileName: strPathAndFileName = arrRelatedBodyPart(i)
Dim strFileName: strFileName = GetFileName(arrRelatedBodyPart(i), "/")
'.AddRelatedBodyPart strPathAndFileName, strFileName, cdoRefTypeId
Set objCDOBodyPart = .AddRelatedBodyPart(strPathAndFileName, strFileName, 1)
objCDOBodyPart.Fields.Item("urn:schemas:mailheader:Content-ID") = "<" & strFileName & ">"
objCDOBodyPart.Fields.Update
Next
What are you using to send the email, I have had success in the past using AspEmail: http://www.aspemail.com/
It explains how to send embedded images here: http://www.aspemail.com/manual_04.html
However you will have to get it installed on your server, if you are using Shared hosting this might be a problem, if you are running your own server pretty easy!

Resources