in my asp code i was using
<%
UserIPAddress = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
If UserIPAddress = "" Then
UserIPAddress = Request.ServerVariables("REMOTE_ADDR")
end if
IF Left(UserIPAddress,11) = "111.111.111" or Left(UserIPAddress,10) = "444.444.44" then
%>
how could i do something like this in asp.net(using vb.net)
Something like this should work:
Dim userIPAddress As String = Request.ServerVariables("HTTP_X_FORWARDED_FOR")
If String.IsNullOrEmpty(userIPAddress) Then
userIPAddress = Request.ServerVariables("REMOTE_ADDR")
End If
If userIPAddress.StartsWith("111.111.111") Or userIPAddress.StartsWith("444.444.44") Then
' Do something
End If
So you'll notice the Request object still exists and in this case works the same. Strings are now objects as well, so typically you wouldn't see any functions like Left. userIPAddress == "" should still work, though I put in String.IsNullOrEmpty().
Related
On a few of the Classic ASP websites I manage for the last few days I have been getting some error notifications (with no error number) that always show an error on a line number where a cookie value is being requested.
Looking at the request for each of these errors, they all have unusual cookies, and look like some sort of hack attempt.
The lines that are indicated as causing the error are all like this:
strCookieCart = Request.Cookies("cart")
Here's a couple of samples of the cookies being sent (truncated)... Note the =true (no name, just a value).
HTTP_COOKIE:=true; yuv=u97Yoe-o0UWp7ho_vaB2csT-xxaQ37gMWzhB1MARTSNk1QKpjJTXmZYMRQ095rM96MaNbhx1tEdJ
HTTP_COOKIE:pll_language=en; =true; yandexuid=6536735381437958890; st=6c9838994ffb
Is Classic ASP incapable of handling these? Is there any way to avoid these errors and ignore the bad values? Are these always likely to be hack attempts or could there be legitimate requests without cookie names?
I suppose I could check for these looking at Request.ServerVariables("HTTP_COOKIE") by manually parsing or using a regular expression check of some sort. Does anyone else do this? Any code to share?
A second answer to my own question and the solution I have now implemented is to add the following code to my common include file.
It tests whether Classic ASP can read the cookies and, using error trapping, ends the response if an error is detected.
On Error Resume Next
Request.Cookies("test")
If Err.Number <> 0 Then Response.End
On Error Goto 0
This is a better solution to my other answer as there is no point in generating a page for what is obviously an attack of some sort so ending the script as soon as possible is a better choice.
My proposed answer to my own question is to create a class that extracts all the valid keys and values for the cookies on initialisation, and has a function to return a value for a specified key.
Unfortunately it doesn't work for cookies that contain a collection of multiple values, but I don't generally use these anyway.
Here is the class:
<%
Class MyRequest
Private m_objCookies
Private Sub Class_Initialize()
Dim strCookies, i, strChar, strName, strValue, blnInValue
strCookies = Request.ServerVariables("HTTP_COOKIE")
Set m_objCookies = Server.CreateObject("Scripting.Dictionary")
i = 1
strName = ""
strValue = ""
blnInValue = False
Do
strChar = Mid(strCookies, i, 1)
If strChar = ";" Or i = Len(strCookies) Then
strValue = Trim(strValue)
If strName <> "" And strValue <> "" Then
If m_objCookies.Exists(strName) Then
m_objCookies.Item(strName) = strValue
Else
m_objCookies.Add strName, strValue
End If
End If
If i = Len(strCookies) Then Exit Do
strName = ""
strValue = ""
blnInValue = False
ElseIf strChar = "=" Then
strName = Trim(strName)
blnInValue = True
ElseIf blnInValue Then
strValue = strValue & strChar
Else
strName = strName & strChar
End If
i = i + 1
Loop
End Sub
Public Function Cookies(strKey)
Cookies = m_objCookies.Item(strKey)
End Function
End Class
%>
The changes to my code to use this class are minimal. Where I currently have...
strCookieCart = Request.Cookies("cart")
I will need to change to...
Dim objMyRequest : Set objMyRequest = New MyRequest
strCookieCart = objMyRequest.Cookies("cart")
I have tested the above with many of the bad requests I have logged and it works fine.
Add three line codes for #johna is answer, after this line:
If strChar = ";" Or i = Len(strCookies) Then
add these lines:
If i = Len(strCookies) And strChar <> ";" Then
strValue = strValue & strChar
End If
For Each Control In Page.Header.Controls
How can I do something as above, at the moment getting the error
"Control is a Type and Cannot be used as an expression"
The Complete Code is as follows
Try
' I only do this on my production servers, so I declare those here.'
If Request.ServerVariables("server_name") = "www.myproductionurl.com" Then
' Allow scripts and css to logged in CMS users'
Dim checkLogin As New Controls.Login
If checkLogin.IsLoggedIn <> True Then
For Each Control In Page.Header.Controls
If Control.GetType.Name = "EktronJsControl" Or Control.GetType.Name = "EktronCssControl" Or Control.GetType.Name = "EktronModalCss" Then
Page.Header.Controls.Remove(Control)
Else
' Removes the extra bubble inline style stuff that wasn't put in a CSS.''
Dim litControl As LiteralControl = Control
If litControl.Text = Nothing Then
litControl.Text = ""
End If
' Removing blank.css file'
Dim htmlLink As HtmlLink = Control
If htmlLink.Href = "/css/blank.css" Then
Page.Header.Controls.Remove(Control)
End If
End If
Next
End If
End If
Catch ex As Exception
End Try`
Sadly... VB.NET compiler says you cannot use "Control" as variable name because "Control" is a type too!!
Just use another identifier :)
Since "Control" is a Class, it can not be used as a variable name. Either change it to another variable name, or surround it in square brackets ... [Control]
The brackets will tell the compiler to treat it as a variable rather than class name.
Change Control variable name to something else.
For Each ctrl In Page.Header.Controls
or
For Each ctrl As Control In Page.Header.Controls
The error message says it all: The word Control is a Type so you need to use something else.
UPDATE in response to comments.
You cannot remove the controls while your using a For Each loop to iterate through them.
Consider changing the code to something like:
For i as Integer = Page.Header.Controls.Length -1 to 0 Step -1
Dim ctrl As Control = CType(Page.Header.Control(i),Control)
If ctrl.GetType.Name = "EktronJsControl" Or ctrl.GetType.Name = "EktronCssControl" Or ctrl.GetType.Name = "EktronModalCss" Then
Page.Header.Controls.Remove(ctrl)
Else
Dim litControl As LiteralControl = ctrl
If litControl.Text = Nothing Then
litControl.Text = ""
End If
End If
Next
Or you could keep a reference to the controls to be removed and remove them after the loop.
Dim removables = New List(Of Control)
For Each ctrl In Page.Header.Controls
If ctrl.GetType.Name = "EktronJsControl" Or ctrl.GetType.Name = "EktronCssControl" Or ctrl.GetType.Name = "EktronModalCss" Then
removables.Add(ctrl)
Else
Dim litControl As LiteralControl = ctrl
If litControl.Text = Nothing Then
litControl.Text = ""
End If
End If
Next
For Each c In removables
Page.Header.Controls.Remove(c)
Next
Also, its unlikely that ctrl will be able to be converted into a LiteralControl and an HtmlLink so you need to add extra checks to determine which it is.
First, I'd like to say I'm sorry that you're working with Ektron :(. I feel your pain.
The syntax of your loop is wrong, you need to specify a variable for your loop. The syntax is:
For Each [variable] As [type] In [collection]
So, change your loop to:
For Each ctrl as Control In Page.Header.Controls
And change all the references for the variable Control in your code to be ctrl.
For more info, see the MSDN article on For Each.
Make a list of Controls to remove after you have enumerated then remove them.
Dim controlsToRemove As New List(Of Control)
For Each ctrl In Page.Header.Controls
If ctrl.GetType.Name = "EktronJsControl" Or ctrl.GetType.Name = "EktronCssControl" Or ctrl.GetType.Name = "EktronModalCss" Then
Page.Header.Controls.Remove(ctrl)
Else
Dim litControl As LiteralControl = ctrl
If litControl.Text = Nothing Then
litControl.Text = ""
End If
Dim htmlLink As HtmlLink = ctrl
If htmlLink.Href = "/css/blank.css" Then
'Page.Header.Controls.Remove(ctrl)
controlsToRemove.Add(ctrl)
End If
End If
Next
For Each ctrlToRemove In controlsToRemove
Page.Header.Controls.Remove(ctrlToRemove )
Next
Is there an equivalent to PHP's get_included_files in classic ASP?
No, there is not.
A very ugly function for that:
<!--#include file="include/common.asp"-->
<%
Function GetIncludedFiles()
Dim Url
Dim Fso
Dim Fs
Dim Src
Dim Arr
Dim Ret
Dim i
Set Fso = Server.CreateObject("Scripting.FileSystemObject")
ReDim Ret(-1)
Url = Request.ServerVariables("URL")
Set Fs = Fso.OpenTextFile(Server.MapPath(Url))
Src = Fs.Readall()
Fs.Close
Set Fs = Nothing
Set Fso = Nothing
Arr = Split(Src, "<" & "!--#include file=")
For i = 0 To UBound(Arr)
Arr(i) = Left(Arr(i), InStr(Arr(i), "-->"))
Arr(i) = Replace(Arr(i), "-", "")
Arr(i) = Replace(Arr(i), "'", "")
Arr(i) = Trim(Replace(Arr(i), """", ""))
If Arr(i) <> "" Then
ReDim Preserve Ret(UBound(Ret) + 1)
Ret(UBound(Ret)) = Arr(i)
End If
Next
GetIncludedFiles = Ret
End Function
Dim File
For Each File In GetIncludedFiles()
Response.Write File & "<br />"
Next
%>
The simple way is to create a main file in a specific directory (for example /include/mainfile.asp) and then include all the other files to this file. Something like:
<!#include File="[your directory here/file1.asp]"-->
<!#include File="[your directory here/file2.asp]"-->
<!#include File="[your directory here/file3.asp]"-->
Then, You can include your main file using "virtual" to the rest of your pages that you want to access those other included files.
<!#include Virtual="/include/mainfile.asp"-->
Not as such, but I vaguely remember seen a tool or two floating around that will give you the equivalent report. It might have been on Code Project or somewhere similar... its been a long time since I last ran across it.
I was just reviewing some old code and found the following (inside foo.asp):
Const ASP_FILENAME = "foo.asp" ' TODO: Update this to the name of this file (if changed)
The variable is only used for logging errors. (ie. "Error in foo.asp - Could not create xxxxx object.") Is there any way to avoid this?
Thanks!
You could parse Request.ServerVariables("url") to get the filename portion. A google search found this code, to which i don't claim credit, which uses the SCRIPT_NAME server variable which seems to make more sense indeed, also taking any url rewriting in to account that might be in place:
function getFileName(fpath, returnExtension)
tmp = fpath
if instrRev(tmp,"/") > 0 then
tmp = mid(tmp, instrRev(tmp,"/")+1)
end if
if returnExtension = false then
if instrRev(tmp,".") > 0 then
tmp = left(tmp, instrRev(tmp,".")-1)
end if
end if
getFileName = tmp
end function
filename = request.ServerVariables("SCRIPT_NAME")
Const ASP_FILENAME = getFileName(filename, true)
From the now-defunct Aspfaq.com (thanks to Archive.org):
How do I get the name of the current URL / page?
This one is pretty easy, but there are two parts.
To retrieve the name of the current file, you can use any of these:
<%
Response.Write Request.ServerVariables("SCRIPT_NAME") & "<br>"
Response.Write Request.ServerVariables("PATH_INFO") & "<br>"
Response.Write Request.ServerVariables("URL") & "<br>"
%>
To make that path local (for example, to use with FileSystemObject), just apply the server.mappath() method to the result.
To get the entire URL, including the http:// or https:// prefix, you can do this:
<%
prot = "http"
https = lcase(request.ServerVariables("HTTPS"))
if https <> "off" then prot = "https"
domainname = Request.ServerVariables("SERVER_NAME")
filename = Request.ServerVariables("SCRIPT_NAME")
querystring = Request.ServerVariables("QUERY_STRING")
response.write prot & "://" & domainname & filename & "?" & querystring
%>
To get the page name ONLY, use something like this:
<%
scr = Request.ServerVariables("SCRIPT_NAME") & "<br>"
if instr(scr,"/")>0 then
scr = right(scr, len(scr) - instrRev(scr,"/"))
end if
response.write scr
%>
Or, without the IF logic:
<%
scr = Request.ServerVariables("SCRIPT_NAME") & "<br>"
loc = instrRev(scr,"/")
scr = mid(scr, loc+1, len(scr) - loc)
response.write scr
%>
Now. If your file is an #INCLUDE within another file, the above scripts will produce the name of the CALLING file (since the included file is first integrated into the calling script, then the ASP within it is all executed in the context of the 'parent' file). One way you can work around this is to re-populate a current_filename variable before loading each include file, for example:
<%
current_filename = "filetoinclude.asp"
%>
<!--#include file='filetoinclude.asp'-->
(And no, don't try passing current_filename as a variable to the #INCLUDE directive; see Article #2042.)
Then, in filetoinclude.asp:
<%
Response.Write "Current file: " & current_filename
%>
Of course, you could just as easily hard-code the filename inside of each include file. But I suppose that solution would somewhat defeat the purpose of retrieving that information at least somewhat dynamically.
I dont know if server.mappath exists on traditional asp, but if so you could use if to know the page filename.
Not saying that anyone here [insert discrete throat clearing cough here] still uses Classic ASP for maintaining and supporting legacy applications, but I recently had the need to do something similar. Refusing to settle for the "it's impossible with Classic ASP" responses out there, I set out to find a way and came up with the following solution.
This approach basically leverages underlying OS commands to literally determine the current filename (whose result is equivalent to using the __FILE__ magic constant in PHP) regardless of whether it's a file include (*.inc) or the script itself (*.asp).
First, to support some sanitization (you can do this some other more "optimal" way if you wish):
'Regex helpers
Function NewRegex(ByVal pattern, ByVal ignore_case, ByVal global)
Set NewRegex = New RegExp
NewRegex.Pattern = pattern
NewRegex.IgnoreCase = ignore_case
NewRegex.Global = global
End Function
Function RegexMatch(ByVal pattern, ByVal subject)
RegexMatch = RegexMatches(subject, pattern, True, False)
End Function
Function RegexMatches(ByVal subject, ByVal pattern, ByVal ignore_case, ByVal global)
RegexMatches = NewRegex(pattern, ignore_case, global).Test(subject)
End Function
And now for a time of "reflection:"
Function GetCurrentFilename(ByVal uniqueId)
'1. Enforce uniqueId format
If Not RegexMatch("^[0-9a-f]+$", uniqueId) Then
Exit Function
End If
'2. Use findstr to scan "readable" files in current directory for uniqueId
Dim shell, cmd, process, fs, filename
Set shell = Server.CreateObject("WScript.Shell")
'See findstr /? for details on switches used below
'cmd = C:\Windows\system32\cmd.exe /c findstr /P /M /C:"uniqueId" "C:\Inetpub\wwwroot\includes\*"
cmd = shell.ExpandEnvironmentStrings("%COMSPEC%") & " /c findstr /P /M /C:""" & uniqueId & """ """ & Server.MapPath(".") & "\*"""
Set process = shell.Exec(cmd)
'3. Use Scripting.FileSystemObject to return the filename portion of the first result returned
Set fs = Server.CreateObject("Scripting.FileSystemObject")
GetCurrentFilename = fs.GetFileName(process.StdOut.ReadLine())
Set fs = Nothing
Set process = Nothing
Set shell = Nothing
End Function
Then, inside whatever file you want to "inspect" the current filename, simply drop the following line, passing in some unique identifier that should not exist in any other file in the current directory but this one:
'myfile.inc
Response.Write "This is in " & GetCurrentFilename("908ab098c")
The result:
This is in somefile.inc
Oh, and if you're interested in what I needed to use this for, here's what it looks like used in a simple breakpoint function:
Function Breakpoint(ByVal line_no, ByVal uniqueId, ByVal msg)
Dim fn
fn = GetCurrentFilename(uniqueId)
Response.Write "[!] Breakpoint hit at Line " & CLng(line_no) & " in " & fn & ": " & Server.HtmlEncode(msg) & vbNewLine
Response.End
End Function
Such that on Line 20 of my code, if I wanted to add my own breakpoint, it would look like this:
Breakpoint 20, "B0001", "Some debug output here"
Output:
[!] Breakpoint hit at Line 20 in somefile.inc: Some debug output here
Happy coding!
I wrote the following function that works about 95% of the time, but I need it to work 100% (obviously):
Public Shared Function getPassedVars() As String
Const keyCount As Integer = 54 ' 54 seems to be the number of parameter keys passed by default (for this web_app).
' there are more if there is a form involved (ie. from search page)
Dim oParams As String = ""
Try
With HttpContext.Current
If .Request.Params.AllKeys.Count > keyCount Then
For i As Integer = 0 To (.Request.Params.AllKeys.Count - (keyCount + 1))
oParams &= String.Format("{0}={1}{2}", .Request.Params.Keys.Item(i), .Request.Params(i), IIf(i < .Request.Params.AllKeys.Count - (keyCount + 1), ";", ""))
Next
End If
End With
Return oParams
Catch ex As Exception
Return Nothing
End Try
End Function
It scrubs the Request.Params object for passed variables, which are in the beginning of the array (the remaining ones are ASP parameters). I am pretty sure I've seen a different way to get these parameters, but I haven't been able to figure it out. Any suggestions?
EDIT
So it looks like I can use the Request.URL.Query to achieve this, I will investigate this and post back.
Here is what I came up with:
Public Shared Function getPassedVars() As String
Dim oParams As String = ""
Dim qString As String = ""
Dim oSplit As New List(Of String)
Try
With HttpContext.Current
qString = .Request.Url.Query
If qString.Length > 0 Then 'do we have any passed variables?
If qString.StartsWith("?") Then qString = qString.Remove(0, 1) 'remove leading ? from querystring if it is there
oSplit.AddRange(qString.Split("&"))
For i As Integer = 0 To oSplit.Count - 1
oParams &= String.Format("{0}{1}", oSplit.Item(i), IIf(i < oSplit.Count - 1, ";", ""))
Next
Return oParams
Else
Return Nothing
End If
End With
Catch ex As Exception
Return Nothing
End Try
End Function
So far so good.
Request.QueryString is a NameValueCollection, so the easiest way to get the "parameters" is to do the following:
foreach (String s in Request.QueryString) {
Response.Write(s + " = " + Request.QueryString[s]);
}
Where is your function located? If it's executing in the page's code behind then you definitely do not need to use the HttpContext variable.
It looks like you are trying to get values from the query string.
For example, for this URL:-
http://www.tempuri.org/mypage.aspx?param1=x¶m2=y
I assume you want retreive the values of the query string parameters param1 and param2?
If so, just use:-
Dim param1 as String = Request.QueryString("param1")
Otherwise, if these parameters are contained in a form (an HTTP POST request) then use the method which Mitchel Sellers suggests.
If you know the name you can use the following to get it by key value
Dim myParamValue as String = Request.Form("MyKeyName")
Otherwise, you can loop through the form collection, by key etc, to get the values. The key is, do you really need to be parsing all 54 items? Or are you simply looking for a few specific values?
httpcontext.Current.Request.QueryString("KeyName")
Request.Params will contain the query parameters you're after.
There's no need to parse the info from Request.URL since it's already done for you.