I'm trying send an HTML string from the client to the server via ajax. I keep getting "disallowed key characters" error. So I took this $config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-'; and set it to nothing $config['permitted_uri_chars'] = ''; Since CodeIgniter says Leave blank to allow all characters -- but only if you are insane. But I still get Disallowed Key Characters error.
This is how I'm trying to send it:
var content = '<p class="MsoNormal">Hi {$first_name}</p>\n<p class="MsoNormal">My name is Bill, etc etc.</p>';
$.get('/task/preview_template', {content:content}, function(data) {
console.log(data); //Disallowed Key Characters
});
_clean_input_keys is your likely culprit for what's throwing the error, and you have a large number of characters that fall outside of the allowed characters of "/^[a-z0-9:_\/-]+$/i".
There are a few ways that I can think of that might handle this:
Modify _clean_input_keys so that it accepts the extra characters. This, of course, is an internal function for a reason and shouldn't be changed unless you know what you're doing. (Alternatively, you may be able to modify it to allow the special characters for HTML encoding and HTML encode the string. This helps mitigate the compromise to security that comes with adding such characters to _clean_input_keys.)
Encode your string before sending it, then decode it on the server side. This is a little more work on both your part, and that of the computers involved, but it keeps _clean_input_keys intact, and should allow you to send your string up, if you can find an encoding that is reliable in both directions and doesn't produce any disallowed characters. Since you're using GET, you may also run into GET input limits on not only the server, but browser-side, as well.
Use POST instead of GET and send your content as a data object. Then just use the $_POST variable on the server, instead of $_GET. While this may work, it is a bit unorthodox and nonstandard usage of the REST verbs.
Store your template content on the server, and reference it by name, instead of storing it in the JavaScript. This, of course, only works if you're not generating your template content on the fly in the JavaScript. If you're using the same template(s) in all of your JavaScript calls, though, then there's really no reason to send that information from JavaScript to begin with.
Related
I have a site where anyone can leave comments.
By leaving a comment browser makes an ajax request to PHP script, sending encodeURIComponent-ed data to PHP script.
Earlier, in the PHP script, I added
$data = str_replace("\n","\\n",str_replace("\"","\\\"",$_POST["text"]));
Now I’ve been testing by inputting random stuff and found an exploit: if to input %00, it will be added to my comments file as null-terminator and corrupts my data. Also, other percent-encoded value will be decoded.
I am sending data as a regular application/x-www-form-urlencoded.
How to fix that?
So, the solution I’ve made so far is:
$_POST["text"] = str_replace("\"","\\\"",$_POST["text"]);
for($i=0;$i<=40;$i++)
if(chr($i)!="\n"&&chr($i)!="\r"&&chr($i)!=" "&&chr($i)!="("&&chr($i)!="&"&&chr($i)!="!"&&chr($i)!="\""&&chr($i)!="'")
$_POST["text"] = str_replace(chr($i),"",$_POST["text"]);
$_POST["text"] = str_replace("\\","",$_POST["text"]);
It just removes all special and potentially malware non-readable characters with some exceptions (newlines, ampersands etc.).
The only issue of this solution is that it removes backslash (but successfully writes data).
I've been visiting stackoverflow.com for a long time and always found the solution to my problem. But this time it's different. That's why I'm posting my first question here.
The situation looks like this: My website provides a directory explorer which allows users to download whole directory as a zip file. The problem is I end up with error when I want to download a dir containg special characters in it's name, i.e. 'c++'. I don't want to force users to NOT name their folders with those special chars, so I need a clue on this one. I noticed that the whole problem comes down to GET protocol. I use ajax POST for example to roll out the directory content, but for making a .zip file and downloading it I need GET:
var dir_clicked = $(e.target).attr('path'); //let's say it equals '/c++'
window.location = 'myDownloadSite.php?directory_path='+dir_clicked;
I studied whole track of dir_clicked variable, step by step, and it seems that the variable in adress is sent correctly (I see the correct url in browser) but typing:
echo $_GET['directory_path']
in myDownloadSite.php prints
'/c'
instead of
'/c++'
Why the GET protocol is cutting my pluses?
You can use:
encodeURIComponent() //to get the url then use
decodeURIComponent() //to decode and access ur filename.
Use urlencode() and urldecode() on server side.
Try encoding your URI with encodeURI(url) JavaScript function.
window.location = encodeURI('myDownloadSite.php?directory_path=' + dir_clicked);
Maybe use encodeURIComponent() and then remove all %xx occurrences?
When the information is posted it is encoded with special chars, sounds like you just need to decode them before using the information.
You can use php function urldecode() to decode the folder names before using them...
$_GET[directory_path]=urldecode($_GET[directory_path]);
im letting my users type in texts, then take them to server side php and process them, and if everything goes as it should, i just append the text with jquery without the page having to load all over again.
This is the procedure:
$post_text = htmlspecialchars(mysql_real_escape_string($_POST['post_text']));
some logic...
everything ok!
stripslashes(str_replace("\\n", "", $post_text))
and then i send all the nessesary data witj json
echo json_encode($return);
on the client side i append the html chunk saved in a variable from the server side.
this seems to work on localhost, it removes all the slashes and so on, but online it just doenst remove the slashes, and they keep coming up, when i hit refresh they dissapear becouse then its a
stripslashes($comment['statusmsg_text'])
written out with php straight from the database. Is it the json that adds some extra stuff? i dont get it becouse it works perfectly on localhost.
best of regards,
alexander
The additional slashes might be magic quotes. You shouldn’t rely on them and disable them.
Additionally, mysql_real_escape_string should only be used to prepare strings to be put into a string context in an MySQL statement. Similar applies to htmlspecialchars that should only be used for sanitizing data to be put into an HTML context.
It may be, that on your server and your localhost the magic_quotes_gpc directive is set differently, so your string is double encoded on server side.
Try it without stripslashes, json_encode should handle that. All you need to do is use mysql_real_escape once, before your string touches your database.
Hey there, I have an Arabic contact script that uses Ajax to retrieve a response from the server after filling the form.
On some apache servers, jQuery.parseJSON() throws an invalid json excepion for the same json it parses perfectly on other servers. This exception is thrown only on chrome and IE.
The json content gets encoded using php's json_encode() function. I tried sending the correct header with the json data and setting the unicode to utf-8, but that didn't help.
This is one of the json responses I try to parse (removed the second part of if because it's long):
{"pageTitle":"\u062e\u0637\u0623 \u0639\u0646\u062f \u0627\u0644\u0625\u0631\u0633\u0627\u0644 !"}
Note: This language of this data is Arabic, that's why it looks like this after being parsed with php's json_encode().
You can try to make a request in the examples given down and look at the full response data using firebug or webkit developer tools. The response passes jsonlint!
Finally, I have two urls using the same version of the script, try to browse them using chrome or IE to see the error in the broken example.
The working example : http://namodg.com/n/
The broken example: http://www.mt-is.co.cc/my/call-me/
Updated: To clarify more, I would like to note that I manged to fix this by using the old eval() to parse the content, I released another version with this fix, it was like this:
// Parse the JSON data
try
{
// Use jquery's default parser
data = $.parseJSON(data);
}
catch(e)
{
/*
* Fix a bug where strange unicode chars in the json data makes the jQuery
* parseJSON() throw an error (only on some servers), by using the old eval() - slower though!
*/
data = eval( "(" + data + ")" );
}
I still want to know if this is a bug in jquery's parseJSON() method, so that I can report it to them.
Found the problem! It was very hard to notice, but I saw something funny about that opening brace... there seemed to be a couple of little dots near it. I used this JavaScript bookmarklet to find out what it was:
javascript:window.location='http://www.google.com/search?q=u+'+('000'+prompt('String?').charCodeAt(prompt('Index?')).toString(16)).slice(-4)
I got the results page. Guess what the problem is! There is an invisible character, repeated twice actually, at the beginning of your output. The zero width non-breaking space is also called the Unicode byte order mark (BOM). It is the reason why jQuery is rejecting your otherwise valid JSON and why pasting the JSON into JSONLint mysteriously works (depending on how you do it).
One way to get this unwanted character into your output is to save your PHP files using Windows Notepad in UTF-8 mode! If this is what you are doing, get another text editor such as Notepad++. Resave all your PHP files without the BOM to fix your problem.
Step 1: Set up Notepad++ to encode files in UTF-8 without BOM by default.
Step 2: Open each existing PHP file, change the Encoding setting, and resave it.
You should try using json2.js (it's on https://github.com/douglascrockford/JSON-js)
Even John Resig (creator of jQuery) says you should:
This version of JSON.js is highly recommended. If you're still using the old version, please please upgrade (this one, undoubtedly, cause less issues than the previous one).
http://ejohn.org/blog/the-state-of-json/
I don't see anything related to parseJSON()
The only difference I see is that in the working example a session-cookie is set(guess it is needed for the "captcha", the mathematical calculation), in the other example no session-cookie is set. So maybe the comparision of the calculation-result fails without the session-cookie.
I have an HTML form POSTing to a PHP page.
I can read in the data using the $_POST variable on the PHP.
However, all the data seems to be escaped.
So, for example
a comma (,) = %2C
a colon (:) = %3a
a slash (/) = %2
so things like a simple URL of such as http://example.com get POSTed as http%3A%2F%2Fexample.com
Any ideas as to what is happening?
Actually you want urldecode. %xx is an URL encoding, not a html encoding. The real question is why are you getting these codes. PHP usually decodes the URL for you as it parses the request into the $_GET and $_REQUEST variables. POSTed forms should not be urlencoded. Can you show us some of the code generating the form? Maybe your form is being encoded on the way out for some reason.
See the warning on this page: http://us2.php.net/manual/en/function.urldecode.php
Here is a simple PHP loop to decode all POST vars
foreach($_POST as $key=>$value) {
$_POST[$key] = urldecode($value);
}
You can then access them as per normal, but properly decoded. I, however, would use a different array to store them, as I don't like to pollute the super globals (I believe they should always have the exact data in them as by PHP).
This shouldn't be happening, and though you can fix it by manually urldecode()ing, you will probably be hiding a basic bug elsewhere that might come round to bite you later.
Although when you POST a form using the default content-type ‘application/x-www-form-encoded’, the values inside it are URL-encoded (%xx), PHP undoes that for you when it makes values available in the $_POST[] array.
If you are still getting unwanted %xx sequences afterwards, there must be another layer of manual URL-encoding going on that shouldn't be there. You need to find where that is. If it's a hidden field, maybe the page that generates it is accidentally encoding it using urlencode() instead of htmlspecialchars(), or something? Putting some example code online might help us find out.