Drupal: Incorrect use of t()? - php

I want to wrap a word in <strong> tags. Is it correct to do that right in the t() call, or am I supposed to do it some other way?
$help = '<p>' . t("Does this sample data look right for node type %node_type? If not, use your browser's <strong>back</strong> button to fix it on the previous page.", array('%node_type' => $_SESSION[NODE_TYPE_KEY])) . '</p>';
Also, what about just dropped variables directly into t(), like this?
foreach ($term_info['term_fields'] as $vocab) {
$options[$vocab] = t($vocab); // TODO: incorrect use of t()?
}

Both your questions are answered in the Drupal API documentation at http://api.drupal.org/api/function/t/6. A short summary:
You can wrap a word in html tags if you really must. Quote:
HTML markup within translation strings
is allowed, but should be avoided if
possible.
It is not allowed to drop variables into t() like you do in your code snippet. Quote:
Because t() is designed for handling
code-based strings, in almost all
cases, the actual string and not a
variable must be passed through t().

Related

Sanitizing data PHP - do i need to escape user inputs that are inside if statements?

I'm sanitizing all user inputs that are output on page, e.g.:
echo escape($user_input);
I have a question about user inputs that are not output to the page but are inside statements - do they need escaped?
Is this OK:
if ($user_input == 'something') { echo escape($another_user_input); }
or should it be:
if (escape($user_input) == 'something') { echo escape($another_user_input); }
Same question for other logic (foreach loops etc.) which would add more faff than this simple example.
The only reason you ever need to escape something is when you're interpolating data into another text medium which gets re-interpreted according to some rules.
E.g.:
echo '<p>' . $somedata . '</p>';
This is programmatically generating HTML which will get interpreted by an HTML parser and will have specific behaviour depending on what's inside $somedata.
$query = 'SELECT foo FROM bar WHERE baz = ' . $somedata;
This is programmatically generating an SQL query which will get interpreted by an SQL parser and will have specific behaviour depending on what's inside $somedata.
If you want to ensure that HTML or that query behaves as you intended, you better make sure you generate those textual commands in a way does that not allow anyone to inject unwanted commands.
if ($somedata == 'something')
Here you're not creating some new text which will be interpreted by something. There's no way for anyone to inject anything here. It's not like PHP is replacing $somedata with the contents of $somedata and then re-interprets that line with the interpolated data. So there's no need to escape this in any way.
Also see The Great Escapism (Or: What You Need To Know To Work With Text Within Text).

"amp;" Precedes $_GET array element (parameter) name

The below link is the issue-although the ".amp;" (I am seeing that my link is not appearing as I pasted it when I view this question before posting. This is exactly what I'm looking to do with my $_GET variable name, remove the amp; from the parameter name)
index.php?SearchResults&SearchString=aliquippa&AllWords=off
The $_GET elements are named with amp; preceding the name I expect. For example, $_GET[amp;AllWords'] is how the variables are named. I expect $_GET['AllWords'] format.
All links on my 'site' are built and returned by a standard class function that applies htmlspecialchars to the final return value. Each link is constructed by a class function specific to the required task and then returned through by calling this standard function. While all links are returned through the same standard function, I have only 1 link misbehaving.
This link is the first time I've tried taking user input and passing it (redirecting?) back through a $_GET parm. It's like the &'s are being doubled up. I am certain the code is not adding a second ampersand.
As a solution, I immediately found and tried htmlspecialchars_decode() against the POST variables. It made no difference with the name assigned to the $_GET parm. Other than decoding what was encoded and going through the logic, I'm at a loss for understanding. The code building the link in error looks the same as the code that is building links that work fine. All links are returned through the standard function, which applies htmlspecialchars. I would think all links either work or do not work, not a mixture.
Below is the code being used for redirect when the $_GET array contains a parm named 'Search' - this is the code I suspect of injecting the double &'s. I have added writing to a log file in this function and the "double &'s" are present in the return value from
Link::ToSearchResults.
if (isset($_GET['Search']))
{
$this->mSearchString = $_POST['search_string'];
$this->mAllWords = isset($_POST['all_words']) ? $_POST['all_words'] : 'off';
ob_clean();
header('HTTP/1.1 302 Found');
header('Location: ' . Link::ToSearchResults($this->mSearchString, $this->mAllWords));
flush();
ob_flush();
ob_end_clean();
exit;
}
Following is the ToSearchResults function code:
$link = 'index.php?SearchResults';
if (empty($searchString))
$link .= '/';
else
$link .= '&SearchString=' . $searchString;
$link .= '&AllWords=' . $allWords;
return self::Build($link);
Following is the return from standard class function Build(). All links are passed through this function before returning to caller.
return htmlspecialchars($link, ENT_QUOTES);
The problem occurs when you pass values containing '&' through the Build method, which is escaping HTML special characters with HTML entities. The resulting link will be of the form:
index.php?SearchResults&SearchString=aliquippa&AllWords=off
PHP's URL parser does not expect to encounter HTML entities, because they should not be present in URLs; it therefore correctly splits the query string on &, treating the trailing amp; as part of the key. To solve the problem, do not pass your URLs through htmlspecialchars().

PHP to communicate with javascript

Static Page A has a form with an action submitting to a Authorization page B which is a dynamic page. After authorization, B will redirect to a callback url C which is passed to B by A.
Besides redirecting to page C, B also post some parameters indicated the auth states. uin is a most important parameter that will be used in the content of page C namely the scripts. The scripts need uin to send Ajax request later. Question is how can I pass uin to the static page C?
A quick and dirty idea I got is to wrap the static page C with a PHP file, and output the data in a hidden div for example:
<?php
$html = file_get_contents("callback.html")
$div = "<div stype='display:none' uin={$_POST['uin']}></div>"
//add this div to $html and print it, need a little more work to figure out how to do this
?>
Is there a better way of doing this , because this is sort of 'idiot' I think...
Your code: (with stype typo fixed)
$div = "<div style=\"display:none\" uin={$_POST['uin']}></div>";
Looking at this code, the biggest problem I can see with it is that you're outputting a $_POST value without doing any escaping on it.
This a potential security threat; consider what would happen if someone provided a form that posted to your site, with the uin value set to a string of HTML code, starting with > to close the div. Their code would appear in your site, exactly as if you'd put it there. With a careful bit of styling, they could use this make your site look and behave however they want. Not great.
You can fix that by using wrapping the $_POST variable in html_entities() so it is properly escaped when it is output to the site.
Or, in this case, since it is (or appears to be) a numeric ID value, you could simply cast it as an int to ensure that it contains no unwanted data, no matter what the actual post data contains:
$uin = (int)$_POST['uin'];
...and then use $uin in the output rather than the raw post data.
The second point I'd make is one of validity. uin is not a valid HTML attribute. It may work, but it's not valid. The correct standards-compliant way to do custom attributes in HTML is to use a data attribute, like so:
$div = "<div style=\"display:none\" data-uin={$uin}></div>";
... ie the names of all custom attributes should start with data-
This is recommended because it allows you to have custom attributes with the same name as real attributes without risking any problems. eg you could have data-style, without colliding with the real style attribute.
It also means that the HTML spec can have new attributes added to it without risking clashes with other people's code. eg if a future version of HTML includes a uin attribute that future browsers use to do something clever with the element, it would cause problems with your code. Those problems would not happen if you use data-uin. (okay, so uin is an unlikely name for a new standard HTML attribute, but the point stands)
Perhaps you should store parameters from page B in user session. Than on page C you can use these parameters (after calling session_start() before anything is outputted to the browser). Also, if you are using javascript, consider placing uin in javascript variable instead of html div. Something like <script type="text/javascript">var uin = 123; </script>.
You have an syntax errors in your php code you need to mask the quotes around your inline style and you missed to add some colons:
<?php
$html = file_get_contents("callback.html");
$div = "<div style=\"display:none\" uin={$_POST['uin']}></div>";
//add this div to $html and print it, need a little more work to figure out how to do this
echo($html); // print variable $html
echo($div); // print variable $div
?>

Htmlspecialchars Not Needed in This Case?

I am developing an application and I am reading up on implementing security measures. I set up a class to automatically generate form elements and the class embeds php string variables within html to create the fields. I noticed, however, that htmlspecialchars() was not necessary as I went to implement it. So I am attempting to pseudo-maliciously turn this:
<input type="text" name="email">... rest of html
into:
<input type="text" name="email"><br><br>
However, both before and after using htmlspecialchars(), my browser gives me this when I try to edit the frontend html:
<input type="text" name="email"><br><br>
Is this just something that is automatically implemented? If so, is this from a PHP update (I thought I found something about it being an update in PHP 5.4)?
Furthermore, Can I abandon using htmlspecialchars()?
Thank you!
EDIT: More information requested
$this->type = 'text' //what I would normally use
$this->type = 'text" name="name"><br><br>' //my attempt to manipulate the html
$output = "<input type='$this->type' name='$this->name'";
$output .= ... close the tag, etc.
echo $output;
The use of htmlspecialchars is required whenever you take some text and insert it into some HTML as a string (unless you know that the text won't contain any characters with special meaning in HTML, but even then using htmlspecialchars is a good habit to be in).
I can't explain why your unspecified input, when run through your unspecified code and then run through a browser's parser (with error recovery features), gives you that output.
After the question was updated:
$this->type = 'text" name="name"><br><br>' //my attempt to manipulate the html
$output = "<input type='$this->type' name='$this->name'";
Your attribute value is delimited with ' characters. Your data doesn't contain any ' characters, so it isn't going to terminate the attribute value and escape.
Try this manipulation:
$this->type = 'text\' name="name"><br><br>' //my attempt to manipulate the html
It should break your HTML, because the delimiters for your attribute value are single quotes, and now they appear in your attribute text as well.
And please make sure not to use any sophisticated DOM inspectors like firebug, but to look at the pure source code that is emitted by your server.

missing ) after argument list

I'll show the main parts of the code as most of it is irrelevant:
$url = $row['url'];
echo "<div id='anything'><img id='$url' src='$cover' alt='$title' onclick='myFunction($url)'>";
and the javascript function:
function myFunction(something) {
alert (something);
}
I recieve the following error in firebug:
missing ) after argument list
[Break On This Error]
myFunction(http://anything.com/anything...
-------------------^
I am relatively new to javascript but I can tell it is obviously not allowing the ":" from the url. However, I can't change or alter the id, as I need to alert the exact id of the Image.
I have made this work in a different format without the php, so I assume it's there where the problem lies?
The URL needs to be a string, but you're just outputting the string's contents.
You could just put quotes around it as suggested elsewhere, but that's at best an incomplete solution.
Fortunately, PHP gives you a better answer: json_encode combined (in your case) with htmlspecialchars. This is a function that (amongst other things) will properly wrap a string for you such that you can use it in JavaScript code. So:
$escapedUrl = htmlspecialchars(json_encode($url));
then
...onclick='myFunction($escapedUrl)'...
json_encode is for encoding text as JSON, but as JSON is a subset of JavaScript literal notation, and json_encode quite happily returns a valid, properly-escaped JavaScript string...
You need the htmlspecialchars as well because you're then outputting the JavaScript code you're generating into the onclick attribute, and the content of all HTML attributes in HTML text (even ones with code in them) must be properly encoded so (for instance) & must be &, etc.
Do this:
$escapedString = json_encode($url);
echo "<div id='anything'><img id='$url' src='$cover' alt='$title' onclick='myFunction($escapedString)'>";
T.J. Crowder is right, and you can check this out for more information:
What is the correct way to escape text in JSON responses?
Why is my first solution incorrect (even if it seems to work with 1 case)?
Read this: http://kunststube.net/escapism/
echo "<div id='anything'><img id='$url' src='$cover' alt='$title' onclick='myFunction(\"$url\")'>";
You basically need to print double quotes around the the value passed into the myFunction call:
onclick='myFunction(\"$url\")'
This is because you are doing something like this:
myFunction(http://anything.com)
Function parameter need to be enclosed within quotes or doble quotes in case of string parameters:
myFunction("http://anything.com")
So your echo should look like:
"<div id='anything'><img id='$url' src='$cover' alt='$title' onclick='myFunction(\"$url\")'>"
Also you should take into account that $url doesn't have to contain valid characters, so you should add some encoding/escaping (think in terms of XSS).
You have to use the encodeURI(uri) function:
"<div id='anything'><img id='$url' src='$cover' alt='$title' onclick='myFunction(encodeURI(\'$url\'))'>";

Categories