Request.Url.Authority doesn't return expected domain - asp.net

I'm generating an e-mail in my website's controller with a link to my website:
"http://" & Request.Url.Authority & "/some-page"
This works when I tested it on my local machine (returns localhost:12345) and in production (returns www.company.com) but 1 person got this as a result:
http://www.company..com/some-page
As you can see there are 2 .. in the domain name. I can't reproduce this error, how is this possible?
Edit: a bit more information
The type of email I'm sending is a plain text email (no HTML or RTF)
The webserver logs show www.company.com as the domain when the problematic request was made
I only received a partial screenshot of the email. I think the email client is Outlook but I see no reason why Outlook would have misinterpreted the link.
It's certainly possible that this person (or malware) has edited the content of this email.

This is actually a problem with how the email is being encoded, see this answer: https://stackoverflow.com/a/6603002/186288. In summary, you should change the encoding to UTF8 to force base-64 encoding of the email, otherwise some email clients can misinterpret the default Content-Transfer-Encoding: Quoted-Printable; encoding and add in extra "."s in URLs that happen to hit a wrap point.
To do this, add this line before you send the email:
mail.BodyEncoding = System.Text.Encoding.UTF8;

I should have tried this sooner with a simple example:
Module Module1
Sub Main()
Dim SomeAddress As New Uri("http://www.example..com/test")
Console.WriteLine(SomeAddress.Authority)
End Sub
End Module
This will throw an exception in the constructor:
System.UriFormatException - Invalid URI: The hostname could not be
parsed
So the customer couldn't have received such an email from my code without editing it.

Why are you using Request.Url.Authority? I suggest you avoid to use it, and use Request.Url.Host. It's better to use Request.Url.Host or Uri class constructor, when consturcting incorrect URI it will throw exception and you can either log it or show error.
Anyway it's hard to predict why one user have got www.company..com Anyway your code with Request.Url.Authority concatenation can not produce it. So maybe error is in other location.

Related

how to forward a link with URI to another link with the same URI

My program directs users to a webpage with their username and password. E.g.
http://example.html?username=username&password=password.
Now I created another page in asp.net and I want some code on example.html to redirect the link to http://example.aspx?username=username&password=password.
So what i want is to get the URI from the first url and direct it to the new url by appending the URI.
Any suggestions?
You can grab the querystring in its entirety via
window.location.search
See this with more about that. Using this, you can extract the parameters, append them to a new URL, and render the link, or set
window.location = "example.aspx" + window.location.search
I believe search comes with "?", but I could be wrong. I assume this is an exmaple; note it's not a good practice to pass the password through a querystring as clear text, especially if you are not using HTTPS. It's generally advisable to do a POST operation, not a GET operation with querystring, when it comes to sensitive information.
Use window.location.search to get everything after "?". Then you can just direct the new aspx page using this java script line.
window.location = "example.aspx" + window.location.search

What is the use of =? in links?

I saw my friend doing some Web Development, and one of his code caught my attention is the Response.Redirect.
What is the use of Home?=, isn't it the LogIn.aspx is the name of the page how come it's still redirecting if it has Home?=. Can someone answer this question of mine please, and explain it very well.
String url = "LogIn.aspx?Home?=" + Username;
Response.Redirect(url);
Update
Working from all your comments, the answer is: The query string parameter name (key) is actually "Home?", not just "Home". Details (including why the code generating that is technically incorrect) below.
how come it's still redirecting if it has Home?=?
Because there's no reason it shouldn't redirect. Granted the URL is invalid (? is a reserved character, it cannot appear unencoded in the query string, so the second ? in the URL is incorrect), but browsers are pretty content to deal with invalid URLs.
Separately, unless Username has already been URL-encoded, the URL could have other errors depending on the content of Username. (All query string parameters must be URL-encoded, in .Net you do that with HttpUtility.UrlEncode.)
Re your comment:
what i mean is i don't know why he use Home?= and what is the use of it
It has no use, it's an error. He probably just meant (no, apparently not, see below after your next comment)
String url = "LogIn.aspx?Home=" + Username;
...which would more correctly be:
String url = "LogIn.aspx?Home=" + HttpUtility.UrlEncode(Username);
(Technically, you have to URL-encode both the keys and values [both "Home" and Username], but the URL-encoded form of "Home" is "Home", so we can get away without making the call for the key. Not true if the key needs to have any of the URL reserved characters in it.)
Re your further comment consisting entirely of this code:
string retrieveValue;
protected void Page_Load(object sender, EventArgs e) {
this.lblUsername.Text = Request.QueryString["Home?";
retrieveValue = this.lblUsername.Text;
}
Assuming the syntax error in the above is fixed (missing ] on line 3), it would appear that he's actually using "Home?" as a key (parameter name). That means the redirect should be:
String url = "LogIn.aspx?" + HttpUtility.UrlEncode("Home?") + "=" + HttpUtility.UrlEncode(Username);
...because the key has a reserved character in it (?). Because that will be decoded for you on receipt, that should make the code above work.
Note that most browsers will probably let you get away with the string as he specified it. It's incorrect, but in a way browsers probably allow.
Regardless of the errors that T.J covered, what he meant to do was load the page LogIn.aspx with the variable "Home" being set to the visitors username. This allows the page to "GET" the variable and use it. Its basically a way of sending data from one page to another.

asp.net response dual content type

i am sending a large amount of excel content data to the browser using Page.Response.Write("") in a for loop.
before starting the loop i am changing the conetnt type of the reponse.context property to "ms-excel".
if i have an exception during that for loop , i try to popup an error message to the browser by registering an HTML startup script block and Write it to the browser. before the write i change back the content type to be text/html.
but i get an error that say that is not possible to change the content type after sending the HTTP Headers.
How to notify the browser about an error that occured during that for loop?
Is it possible to have more that one respone to the same browser tab?
by the way,right now i don't want to use ASP.NET AJAX.
Did you try Response.ClearHeaders(); before changing the context type?
If that doesn't work because your Response.Write is causing problems, you might think about going the route of building a string before deciding your content type and then setting the headers.
Loop trough the content and add to a StringBuilder
If no error, set contenttype to ms-excel and write out SB
If there is an error, leave contenttype as it is write out your error message as needed.
Page.Response.Write("") will send data to the browser. When you do that the browser needs to know the type of content it gets in order to render it correct. If you already told the browser what kind of content you have(and even if you don't, you are already sening data with Response.Write, it will use the default value which I think is text/html) then you can't take it back. Whatever you are saying to the client is said and you can't take it back.
The way to solve your problem is to cache the reply as suggested by Doozer.
/Tibi

What can cause "The specified string is not in the form required for an e-mail address"?

What can cause the error "The specified string is not in the form required for an e-mail address"?
Source code line that causes the error:
msg.To.Add(new MailAddress("txtEmail.Text"));
msg.To.Add(new MailAddress("txtEmail.Text"));
is the problem. txtEmail.Text is not an e-mail address. If that's a text file that's a list of e-mails, you're going to need to open it and read it and pass them in one by one.
If it's referring to a textbox, take the quotes around it off. Like this:
msg.To.Add(new MailAddress(txtEmail.Text));
For me, the problem was using semi-colon(;) to seperate multiple emails.
Once I change it to comma(,) it works.
Hope this helps someone.
The issue on the code above might have occured due to
msg.To.Add(new MailAddress("txtEmail.Text"));
You might be clear that here "txtEmail.Text" appears as a string but not the mailing address to whom the mail is to be send. So code should be replaced with
msg.To.Add(new MailAddress(txtEmail.Text));
and sometimes the error like "The specified string is not in the form required for an e-mail address" might also occur due to use of improper string.As even I faced it.
Basically I was working in email sending task using the ASP.Net. The main issue for me was sending mail to multiple users. Firstly, I retrieved the email address from database and used " ; " so as to separate the multiple email addresses. Because while sending the email to multiple users, in regular basis we use semicolon i.e. " ;"
Everything seemed ok but after compilation I got the error "The specified string is not in the form required for an e-mail address".
After a bit analysis, I came to know that instead of using the " ; " we should use " , " so as to separate multiple email address while sending mails . This is the formatted string for separating the emails.
For Details visit: http://kopila.com.np
Thank you!
both the sender and recipient address need to be a valid email address format. eg. user#domain.com
Hmm, let me see, is it possible that "txtEmail.Text" is not a valid email address? I'm just guessing here, but you might want to remove the quotes from around that to get the actual value in your control...
Guess what the issue was for us?
Trailing spaces. For some reason, when you use a multi-line text box, spaces are added to the front of the string.
When we used Trim on the string, it worked fine.
I had a problem where I was creating the message with the recipient and the sender already in it, but it returned the following error:
The specified string is not in the form required for an e-mail address
The problematic code was as follows:
MailMessage objMsg = new MailMessage(regEmail.Text.ToString(), "me#mysite.com");
I fixed the issue by replacing that code with this:
MailMessage objMsg = new MailMessage();
objMsg.From = new MailAddress(regEmail.Text.ToString());
objMsg.To.Add(new MailAddress("me#mysite.com"));
It is also helpful to use a regular expression validator in your user control to make sure the address is valid, you can use the following code for asp:
<asp:RegularExpressionValidator ID="regex1" ControlToValidate="regEmail" ErrorMessage="Please enter a valid email address" ValidationExpression="^[\w-\.]+#([\w-]+\.)+[\w-]{2,4}$" ValidationGroup="regGroup" runat="server" Display="None" SetFocusOnError="True"></asp:RegularExpressionValidator>
Or if you'd prefer to validate the email in C# then you can use this as also stated by S Fadhel Ali:
public static bool IsValidEmail(String Email)
{
if( Email != null && Email != "" )
return Regex.IsMatch(Email, #"\w+([-+.]\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*" );
else
return false;
}
It should be in the following format.
Dim myMail As New Net.Mail.MailMessage(New MailAddress(strFrom), New MailAddress(strTo))

"name" web pdf for better default save filename in Acrobat?

My app generates PDFs for user consumption. The "Content-Disposition" http header is set as mentioned here. This is set to "inline; filename=foo.pdf", which should be enough for Acrobat to give "foo.pdf" as the filename when saving the pdf.
However, upon clicking the "Save" button in the browser-embedded Acrobat, the default name to save is not that filename but instead the URL with slashes changed to underscores. Huge and ugly. Is there a way to affect this default filename in Adobe?
There IS a query string in the URLs, and this is non-negotiable. This may be significant, but adding a "&foo=/title.pdf" to the end of the URL doesn't affect the default filename.
Update 2: I've tried both
content-disposition inline; filename=foo.pdf
Content-Type application/pdf; filename=foo.pdf
and
content-disposition inline; filename=foo.pdf
Content-Type application/pdf; name=foo.pdf
(as verified through Firebug) Sadly, neither worked.
A sample url is
/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true
which translates to a default Acrobat save as filename of
http___localhost_bar_sessions_958d8a22-0_views_1493881172_export_format=application_pdf&no-attachment=true.pdf
Update 3: Julian Reschke brings actual insight and rigor to this case. Please upvote his answer.
This seems to be broken in FF (https://bugzilla.mozilla.org/show_bug.cgi?id=433613) and IE but work in Opera, Safari, and Chrome. http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf
Part of the problem is that the relevant RFC 2183 doesn't really state what to do with a disposition type of "inline" and a filename.
Also, as far as I can tell, the only UA that actually uses the filename for type=inline is Firefox (see test case).
Finally, it's not obvious that the plugin API actually makes that information available (maybe someboy familiar with the API can elaborate).
That being said, I have sent a pointer to this question to an Adobe person; maybe the right people will have a look.
Related: see attempt to clarify Content-Disposition in HTTP in draft-reschke-rfc2183-in-http -- this is early work in progress, feedback appreciated.
Update: I have added a test case, which seems to indicate that the Acrobat reader plugin doesn't use the response headers (in Firefox), although the plugin API provides access to them.
Set the file name in ContentType as well. This should solve the problem.
context.Response.ContentType = "application/pdf; name=" + fileName;
// the usual stuff
context.Response.AddHeader("content-disposition", "inline; filename=" + fileName);
After you set content-disposition header, also add content-length header, then use binarywrite to stream the PDF.
context.Response.AddHeader("Content-Length", fileBytes.Length.ToString());
context.Response.BinaryWrite(fileBytes);
Like you, I tried and tried to get this to work. Finally I gave up on this idea, and just opted for a workaround.
I'm using ASP.NET MVC Framework, so I modified my routes for that controller/action to make sure that the served up PDF file is the last part of the location portion of the URI (before the query string), and pass everything else in the query string.
Eg:
Old URI:
http://server/app/report/showpdf?param1=foo&param2=bar&filename=myreport.pdf
New URI:
http://server/app/report/showpdf/myreport.pdf?param1=foo&param2=bar
The resulting header looks exactly like what you've described (content-type is application/pdf, disposition is inline, filename is uselessly part of the header). Acrobat shows it in the browser window (no save as dialog) and the filename that is auto-populated if a user clicks the Acrobat Save button is the report filename.
A few considerations:
In order for the filenames to look decent, they shouldn't have any escaped characters (ie, no spaces, etc)... which is a bit limiting. My filenames are auto-generated in this case, and before had spaces in them, which were showing up as '%20's in the resulting save dialog filename. I just replaced the spaces with underscores, and that worked out.
This is by no names the best solution, but it does work. It also means that you have to have the filename available to make it part of the original URI, which might mess with your program's workflow. If it's currently being generated or retrieved from a database during the server-side call that generates the PDF, you might need to move the code that generates the filename to javascript as part of a form submission or if it comes from a database make it a quick ajax call to get the filename when building the URL that results in the inlined PDF.
If you're taking the filename from a user input on a form, then that should be validated not to contain escaped characters, which will annoy users.
Hope that helps.
Try placing the file name at the end of the URL, before any other parameters. This worked for me.
http://www.setasign.de/support/tips-and-tricks/filename-in-browser-plugin/
In ASP.NET 2.0 change the URL from
http://www. server.com/DocServe.aspx?DocId=XXXXXXX
to
http://www. server.com/DocServe.aspx/MySaveAsFileName?DocId=XXXXXXX
This works for Acrobat 8 and the default SaveAs filename is now MySaveAsFileName.pdf.
However, you have to restrict the allowed characters in MySaveAsFileName (no periods, etc.).
Apache's mod_rewrite can solve this.
I have a web service with an endpoint at /foo/getDoc.service. Of course Acrobat will save files as getDoc.pdf. I added the following lines in apache.conf:
LoadModule RewriteModule modules/mod_rewrite.so
RewriteEngine on
RewriteRule ^/foo/getDoc/(.*)$ /foo/getDoc.service [P,NE]
Now when I request /foo/getDoc/filename.pdf?bar&qux, it gets internally rewritten to /foo/getDoc.service?bar&qux, so I'm hitting the correct endpoint of the web service, but Acrobat thinks it will save my file as filename.pdf.
If you use asp.net, you can control pdf filename through page (url) file name.
As other users wrote, Acrobat is a bit s... when it choose the pdf file name when you press "save" button: it takes the page name, removes the extension and add ".pdf".
So /foo/bar/GetMyPdf.aspx gives GetMyPdf.pdf.
The only solution I found is to manage "dynamic" page names through an asp.net handler:
create a class that implements IHttpHandler
map an handler in web.config bounded to the class
Mapping1: all pages have a common radix (MyDocument_):
<httpHandlers>
<add verb="*" path="MyDocument_*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>
Mapping2: completely free file name (need a folder in path):
<add verb="*" path="/CustomName/*.ashx" type="ITextMiscWeb.MyDocumentHandler"/>
Some tips here (the pdf is dynamically created using iTextSharp):
http://fhtino.blogspot.com/2006/11/how-to-show-or-download-pdf-file-from.html
Instead of attachment you can try inline:
Response.AddHeader("content-disposition", "inline;filename=MyFile.pdf");
I used inline in a previous web application that generated Crystal Reports output into PDF and sent that in browser to the user.
File download dialog (PDF) with save and open option
Points To Remember:
Return Stream with correct array size from service
Read the byte arrary from stream with correct byte length on the basis of stream length.
set correct contenttype
Here is the code for read stream and open the File download dialog for PDF file
private void DownloadSharePointDocument()
{
Uri uriAddress = new Uri("http://hyddlf5187:900/SharePointDownloadService/FulfillmentDownload.svc/GetDocumentByID/1/drmfree/");
HttpWebRequest req = WebRequest.Create(uriAddress) as HttpWebRequest;
// Get response
using (HttpWebResponse httpWebResponse = req.GetResponse() as HttpWebResponse)
{
Stream stream = httpWebResponse.GetResponseStream();
int byteCount = Convert.ToInt32(httpWebResponse.ContentLength);
byte[] Buffer1 = new byte[byteCount];
using (BinaryReader reader = new BinaryReader(stream))
{
Buffer1 = reader.ReadBytes(byteCount);
}
Response.Clear();
Response.ClearHeaders();
// set the content type to PDF
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment;filename=Filename.pdf");
Response.Buffer = true;
Response.BinaryWrite(Buffer1);
Response.Flush();
// Response.End();
}
}
I believe this has already been mentioned in one flavor or another but I'll try and state it in my own words.
Rather than this:
/bar/sessions/958d8a22-0/views/1493881172/export?format=application/pdf&no-attachment=true
I use this:
/bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf?GeneratePDF=1
Rather than having "export" process the request, when a request comes in, I look in the URL for GeneratePDF=1. If found, I run whatever code was running in "export" rather than allowing my system to attempt to search and serve a PDF in the location /bar/sessions/958d8a22-0/views/1493881172/NameThatIWantPDFToBe.pdf. If GeneratePDF is not found in the URL, I simply transmit the file requested. (note that I can't simply redirect to the file requested - or else I'd end up in an endless loop)
You could always have two links. One that opens the document inside the browser, and another to download it (using an incorrect content type). This is what Gmail does.
For anyone still looking at this, I used the solution found here and it worked wonderfully. Thanks Fabrizio!
The way I solved this (with PHP) is as follows:
Suppose your URL is SomeScript.php?id=ID&data=DATA and the file you want to use is TEST.pdf.
Change the URL to SomeScript.php/id/ID/data/DATA/EXT/TEST.pdf.
It's important that the last parameter is the file name you want Adobe to use (the 'EXT' can be about anything). Make sure there are no special chars in the above string, BTW.
Now, at the top of SomeScript.php, add:
$_REQUEST = MakeFriendlyURI( $_SERVER['PHP\_SELF'], $_SERVER['SCRIPT_FILENAME']);
Then add this function to SomeScript.php (or your function library):
function MakeFriendlyURI($URI, $ScriptName) {
/* Need to remove everything up to the script name */
$MyName = '/^.*'.preg_quote(basename($ScriptName)."/", '/').'/';
$Str = preg_replace($MyName,'',$URI);
$RequestArray = array();
/* Breaks down like this
0 1 2 3 4 5
PARAM1/VAL1/PARAM2/VAL2/PARAM3/VAL3
*/
$tmp = explode('/',$Str);
/* Ok so build an associative array with Key->value
This way it can be returned back to $_REQUEST or $_GET
*/
for ($i=0;$i < count($tmp); $i = $i+2){
$RequestArray[$tmp[$i]] = $tmp[$i+1];
}
return $RequestArray;
}//EO MakeFriendlyURI
Now $_REQUEST (or $_GET if you prefer) is accessed like normal $_REQUEST['id'], $_REQUEST['data'], etc.
And Adobe will use your desired file name as the default save as or email info when you send it inline.
I was redirected here because i have the same problem. I also tried Troy Howard's workaround but it is doesn't seem to work.
The approach I did on this one is to NO LONGER use response object to write the file on the fly. Since the PDF is already existing on the server, what i did was to redirect my page pointing to that PDF file. Works great.
http://forums.asp.net/t/143631.aspx
I hope my vague explanation gave you an idea.
Credits to Vivek.
Nginx
location /file.pdf
{
# more_set_headers "Content-Type: application/pdf; name=save_as_file.pdf";
add_header Content-Disposition "inline; filename=save_as_file.pdf";
alias /var/www/file.pdf;
}
Check with
curl -I https://example.com/file.pdf
Firefox 62.0b5 (64-bit): OK.
Chrome 67.0.3396.99 (64-Bit): OK.
IE 11: No comment.
Try this, if your executable is "get.cgi"
http://server,org/get.cgi/filename.pdf?file=filename.pdf
Yes, it's completely insane. There is no file called "filename.pdf" on the server, there is directory at all under the executable get.cgi.
But it seems to work. The server ignores the filename.pdf and the pdf reader ignores the "get.cgi"
Dan

Resources