Remove Codeigniter label wrapping lang() - php

How do I remove the auto label wrapping that is for the lang() in Codeigniter.
The manual doesn't say anything about it: https://www.codeigniter.com/user_guide/helpers/language_helper.html
Do I have to write a function by myself or is there a simple clean way that Im missing?

Don't write the second parameter. Keep it empty.

Take a look at the lang function (found in: /system/helpers/language_helper.php):
function lang($line, $for = '', $attributes = array())
{
$CI =& get_instance();
$line = $CI->lang->line($line);
if ($for !== '')
{
$line = '<label for="'.$for.'"'._stringify_attributes($attributes).'>'.$line.'</label>';
}
return $line;
}
As you can see it takes 3 parameters. The first parameter is required, but the second two are optional. If you state a second parameter it will return the language string wrapped in a label.
So stating only the first parameter should make it output just the language string.
UPDATE:
From reading your comment it sounds like you would be better off using the language class directly. However the language class alone will not be enough, you will need to extend it for your purpose. To do this you can create a new file in your application/core folder called MY_lang.php.
class MY_Lang extends CI_Lang {
// You want to extend the line function
function line($line = '', $value = '')
{
$line = ($line == '' OR ! isset($this->language[$line])) ? FALSE : $this->language[$line];
// We can assume that if a value is passed it is intended to be inserted into the language string
if($value) {
$line = sprintf($line, $value);
}
// Because killer robots like unicorns!
if ($line === FALSE)
{
log_message('error', 'Could not find the language line "'.$line.'"');
}
return $line ;
}
}
Assuming your language file has a string like so:
$lang['welcome_text'] = "Welcome %s";
You could then use this by loading the language class, and using the following code:
$name = "foo";
$this->lang->line('welcome_text', $name);
The above is 100% untested, so it may need some tweeking, but it should give you somewhere to start from.

Related

codeigniter 3 URI routing - geting right hand side from given url

I need to simulate routing in Codeigniter 3, so my question is how to get the right-hand side from any URL programmatically?
for example, some routes that I have:
$route["blog"] = "Main/blog/en";
$route["blog/(:any)"] = "Main/blog/en/$1";
$route["novosti"] = "Main/blog/sr";
$route["novosti/(:any)"] = "Main/blog/sr/$1";
$route["contact"] = "Main/contact/en";
$route["kontakt"] = "Main/contact/sr";
Now I need a function that can return right-hand side for a given URL part something like this:
echo $this->route->item("novosti/petar")
should print then Main/blog/sr/$1 or Main/blog/sr/petar
Is there such a function in Codeigniter, because I can't find it in documentation?
UPDATE:
I am looking throughout system/router class and I see that protected function _parse_routes is doing something similar so if there is no function that can give me what I need I will create one based on this one.
use this
$this->router->routes['blog']
you will get
Main/blog/en
Codeigniter is simple, too simple... And because it is not obvious for me where that function is (if exists at all) I've just adopted _parse_routes to parse URL (slug) into the right-hand side from which I can find the corresponding file much easier.
Here it is (if someone gets in the same situation I was).
function parseRoute($uri) {
// Get HTTP verb
$http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';
// Loop through the route array looking for wildcards
foreach ($this->router->routes as $key => $val) {
// Check if route format is using HTTP verbs
if (is_array($val)) {
$val = array_change_key_case($val, CASE_LOWER);
if (isset($val[$http_verb])) {
$val = $val[$http_verb];
} else {
continue;
}
}
// Convert wildcards to RegEx
$key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);
// Does the RegEx match?
if (preg_match('#^' . $key . '$#', $uri, $matches)) {
// Are we using callbacks to process back-references?
if (!is_string($val) && is_callable($val)) {
// Remove the original string from the matches array.
array_shift($matches);
// Execute the callback using the values in matches as its parameters.
$val = call_user_func_array($val, $matches);
}
// Are we using the default routing method for back-references?
elseif (strpos($val, '$') !== FALSE && strpos($key, '(') !== FALSE) {
$val = preg_replace('#^' . $key . '$#', $val, $uri);
}
return $val;
}
}
// If we got this far it means we didn't encounter a
// matching route so we'll set the site default route
return null;
}
Now, this:
echo parseRoute("novosti/petar")
will produce:
Main/blog/sr/petar
AKA: Controler class / function inside that controller / language param / blog article
You can fetch the required info using the below code.
$this->router->routes['novosti/(:any)'];

PHP/Laravel Check a condition in a function only once

I have written a custom translation function for Laravel, which first checks a configuration variable to see whether to use Laravel's default __() function or my custom trans() function.
Here's my function:
function t($key, $replace = [], $locale = null)
{
$source = Config::get('translate.source');
if ($source == 'database') {
return trans($key, $replace, $locale);
} else {
return __($key, $replace, $locale);
}
}
However, for speed purposes, I don't want the if condition to run reach time I call the t() function, but only on the first call.
Any ideas?
You want to set a variable in the class and refer to that. So, create a variable databaseSource:
private $databaseSource = false;
You then want a method that will change the boolean:
function updateSource()
{
$source = Config::get('translate.source');
if ($source == 'database') {
$this->databaseSource = true;
}
$this->databaseSource = false;
}
You can then use this piece of functionality over and over via accessing the variable instead of getting the source every time you need it.
E.g. if ($databaseSource) { ... }

How to secure a template engine in PHP from injection

I am currently trying to create a simple template engine in PHP. The main thing I care about is security, however template tutorials do not. Lets say I have a database table with a username and his description. The user can type whatever he wants there.
My guess would be to use htmlspecialchars() function, to prevent javascript and html injection. But what about 'template code injection'? If my template rule is to replace [#key] to "value", the user can update his description that interferes with my template handler. Should I treat "[", "#", "]" as special characters and replace them with their ascii code when using my set method?
template.php:
class Template {
protected $file;
protected $values = array();
public function __construct($file) {
$this->file = $file;
}
public function set($key, $value) {
$this->values[$key] = $value;
}
public function output() {
if (!file_exists($this->file)) {
return "Error loading template file ($this->file).";
}
$output = file_get_contents($this->file);
foreach ($this->values as $key => $value) {
$tagToReplace = "[#$key]";
$output = str_replace($tagToReplace, $value, $output);
}
return $output;
}
}
example.tpl:
Username: [#name]
About me: [#info]
index.php:
include 'template.php';
$page = new Template('example.tpl');
$page->set('info', '[#name][#name][#name]I just injected some code.');
$page->set('name', 'Tom');
echo $page->output();
This would display:
Username: Tom
About me: TomTomTomI just injected some code.
The code I used is based on:
http://www.broculos.net/2008/03/how-to-make-simple-html-template-engine.html
Change your function to search in the unchanged template only once for the known keys:
public function output() {
if (!file_exists($this->file)) {
return "Error loading template file ($this->file).";
}
$output = file_get_contents($this->file);
$keys = array_keys($this->values);
$pattern = '$\[#(' . implode('|', array_map('preg_quote', $keys)) . ')\]$';
$output = preg_replace_callback($pattern, function($match) {
return $this->values[$match[1]];
}, $output);
return $output;
}
I was thinking about it and I think this solution is fastest and simplest:
foreach ($this->values as $key => $value) {
$tagToReplace = "[#$key]";
if (strpos($output, "[#$value]") !== FALSE)
$value = '['.substr($value,1,-1).']';
$output = str_replace($tagToReplace, $value, $output);
}
It replaces brackets in value with html entity string if [$value] is in output.
Used this html entity list
For future adopters:
This kind of solution is OK if Template Parser is implemented by loading non-interpeted/non-evaled file (as is OP's case by loading local file using file_get_contents). However, if it's implemented by INCLUDING PHP view, beware that this check won't handle the case when you put some user-modifiable data from database into view directly (without using parser, e.g. <?=$var;?>) and then use template parser for this view. In that case, parser has no way to know if these data are part of template structure and this check won't work for them. (I don't know how should this case be handled properly.) Anyhow, I think best practice is to never pass sensitive data to template parser, even if you don't use them in your template. When attacker then tricks parser to eval his custom data, he won't get information he didn't already have. Even better, don't use template parser.

How can I find out the name of a variable inside a function?

I have a function
function my_dump($a,$name){
echo '<pre>'.$name.":\n";
var_export($a);
echo '</pre>';
}
How can I achieve this with only one argument so the function recognizes the name of the called variable itself?
for example:
my_dump($cool_variable_name);
will output:
Name: "cool_variable_name"
Content: array(...
If you need to debug code, then using tools like xdebug is a lot more flexible and efficient than homebrew variable dumps; but debug_backtrace() (although a big overhead) might give you what you need. Extract the filename and line number of the call to your debug dump function, and parse that line to extract the variable name that's used when calling the function
function my_dump($a) {
$backtrace = debug_backtrace()[0];
$fh = fopen($backtrace['file'], 'r');
$line = 0;
while (++$line <= $backtrace['line']) {
$code = fgets($fh);
}
fclose($fh);
preg_match('/' . __FUNCTION__ . '\s*\((.*)\)\s*;/u', $code, $name);
echo '<pre>'.trim($name[1]).":\n";
var_export($a);
echo '</pre>';
}
$foo = 'bar';
$baz = array(
'Hello',
'World'
);
my_dump($foo);
my_dump(
$baz
);
If your PHP version doesn't support array dereferencing, change
$backtrace = debug_backtrace()[0];
to
$backtrace = debug_backtrace();
$backtrace = $backtrace[0];
If your call to my_dump() spans multiple lines (like my $baz example), you'll need a slightly more sophisticated parser to extract the variable name from your code.
function my_dump($a) {
$backtrace = debug_backtrace()[0];
$fh = fopen($backtrace['file'], 'r');
$line = 0;
while (++$line <= $backtrace['line']) {
$code = fgets($fh);
}
fclose($fh);
preg_match('/' . __FUNCTION__ . '\s*\((.*)\)\s*;/u', $code, $name);
echo '<pre>'.trim($name[1]).":\n";
var_export($a);
echo '</pre>';
}
It does not run right - because used expression does not give correct result.
Using of \s* has not sense because nothing can be between name of function and brackets with parameters.
Using of ; in expression has not sense too. At least because is allows only standalone using of this function where result of this function is given to else variable. But sometimes it may be needed to use this function as parameter.
And using of (.*) will allow also all that is behind variable name given as parameter - even if there is semicolon.
So, it is needed to exclude of sign of end bracket, ), from result. There are many ways how to do that.
You can use form from code of function below or this (or something else)
'/'.__FUNCTION__.'\((\w+)\)/'
Whole function may be very simplified into (for example, this is case of class function):
protected function Get_VariableNameAsText($Variable="")
{
$File = file(debug_backtrace()[0]['file']);
for($Line = 1; $Line < count($File); $Line++)
{
if($Line == debug_backtrace()[0]['line']-1)
{
preg_match('/'.__FUNCTION__.'\(([^\)]*)\)/', $File[$Line], $VariableName);
return trim($VariableName[1]);
}
}
}
I deleted using of var_export because I don't see why to use it, when I only want to get variable name as string (text). And printing of given string is better outside of this function.
If you have not 5.4 or greater, you need to change code
$File = file(debug_backtrace()[0]['file']);
if($Line == debug_backtrace()[0]['line']-1)
on
$Trace = debug_backtrace();
$File = file($Trace[0]['file']);
if($Line == $Trace[0]['line']-1)
... I beg your pardon for new answer instead change of previous, but it would be too long (and thus uncomfortable) for reading.
Below is function from previous answer, that is improved for multiple usage of this function. This version is capable to get name of correct variable in case of multiple usage in one line.
It is not capable to get name of more than one variable - at least because I don't think it would be good (useful for anything).
Differences:
adding of integer parameter $Index
new function for regular expression
new regular expression
new handling of result of regular expression
parameter $Index is not demanded - but its ignoring whenever else than the first usage of that function will give wrong result
\x20 in expression means space
exception class and exception message in try-catch block may be rewritten as you need
protected status of function may be changed or deleted
protected function Get_VariableNameAsText($Variable="", $Index="")
{
$File = file(debug_backtrace()[0]['file']);
try
{
if(!empty($Index) && !is_integer($Index))
{
throw new UniT_Exception(UniT_Exception::UNIT_EXCEPTIONS_MAIN_PARAM, UniT_Exception::UNIT_EXCEPTIONS_PARAM_VALTYPE);
}
}
catch(UniT_Exception $Exception)
{
$Exception -> ExceptionWarning(__CLASS__, __FUNCTION__, $this -> Get_Parameters(__CLASS__, __FUNCTION__)[1], gettype($Index), 'integer');
}
for($Line = 1; $Line < count($File); $Line++)
{
if($Line == debug_backtrace()[0]['line']-1)
{
preg_match_all('/'.__FUNCTION__.'\((?<type>[a-z]{1,}\:{2}\${1}|\$this\x20{0,1}\-\>{1}\x20{0,1}|\${1})(?<variable>[A-Za-z0-9_]{1,})\x20{0,1}\,{0,1}\x20{0,1}(?<index>[0-9]{0,})\x20{0,}\)/', $File[$Line], $VariableName, PREG_SET_ORDER);
if(empty($Index))
{
return $VariableName[0]['type'].$VariableName[0]['variable'];
}
else
{
return $VariableName[$Index]['type'].$VariableName[$Index]['variable'];
}
}
}
}
I hope it will help you, like or better than previous version.
Edit: New expression allows using of more types of variables (not only common).
If it is a simple script, where all variables are defined in the global scope, you could get for the $GLOBALS solution:
function my_dump($a){
if(is_string($a) and isset($GLOBALS[$a])) {
echo "varname: $a\n";
$a=&$GLOBALS[$a];
}
echo '<pre>'.$name.":\n";
var_export($a);
echo '</pre>';
}
this way you can call the dump function with the variable name instead
my_dump("cool_variable_name");
instead of
my_dump($cool_variable_name);
There is no way to do this.
When the function is called the value of the parameter gets pasted into your $a , so every attempt to get the name of it would return "a".
http://us3.php.net/get_defined_vars will fail, because it only returns variables inside your function (that means "a").
You may use an array with one item, but I guess that's not what you intend to do.

php str_replace template with placeholders

I have one array for data
$data = array(title=>'some title', date=>1350498600, story=>'Some story');
I have a template
$template = "#title#, <br>#date(d)#<br> #date(m)#<br>#date(Y)#<br> #story#";
All i want is to fit data into template and i know that can be done by str_replace but my problem is the date format. date format is coming from the template not from the data, in data date is stored as php date.
yesterday i tried to ask the same question but i think my question wasn't clear.
Anybody please help me.
i think it won't work with str_replace easily so i'm going to use preg_replace
$data = array('title'=>'some title', 'date'=>1350498600, 'story'=>'Some story');
$template = "#title#, <br>#date(d)#<br> #date(m)#<br>#date(Y)#<br> #story#";
$result = preg_replace_callback('/#(\w+)(?:\\((.*?)\\))?#/', function ($match) use($data) {
$value = isset($data[$match[1]]) ? $data[$match[1]] : null;
if (!$value) {
// undefined variable in template throw exception or something ...
}
if (! empty($match[2]) && $match[1] == "date") {
$value = date($match[2], $value);
}
return $value;
}, $template);
Instead of using date(m) or date(Y) you could also do things like
date(d-m-Y) using this snippet
This has the disadvantage that you can format only the date variable using this mechanism. But with a few tweaks you can extend this functionality.
Note: If you use a PHP version below 5.3 you can't use closures but you can do the following:
function replace_callback_variables($match) {
global $data; // this is ugly
// same code as above:
$value = isset($data[$match[1]]) ? $data[$match[1]] : null;
if (!$value) {
// undefined variable in template throw exception or something ...
}
if (! empty($match[2]) && $match[1] == "date") {
$value = date($match[2], $value);
}
return $value;
}
$data = array('title'=>'some title', 'date'=>1350498600, 'story'=>'Some story');
$template = "#title#, <br>#date(d)#<br> #date(m)#<br>#date(Y)#<br> #story#";
// pass the function name as string to preg_replace_callback
$result = preg_replace_callback('/#(\w+)(?:\\((.*?)\\))?#/', 'replace_callback_variables', $template);
You can find more information about callbacks in PHP here
I'd suggest using a templating engine like so:
https://github.com/cybershade/CSCMS/blob/master/core/classes/class.template.php
And then your templates turn out like this:
https://github.com/cybershade/CSCMS/blob/master/themes/cybershade/site_header.tpl
and
https://github.com/cybershade/CSCMS/blob/master/modules/forum/views/viewIndex/default.tpl
Download this file: http://www.imleeds.com/template.class.txt
Rename the extension to .PHP from .TXT
This is something I created years ago, I keep my HTML away from my PHP, always. So see an example below.
<?php
include("template.class.php");
//Initialise the template class.
$tmpl = new template;
$name = "Richard";
$person = array("Name" => "Richard", "Domain" => "imleeds.com");
/*
On index.html, you can now use: %var.name|Default if not found% and also, extend further, %var.person.Name|Default%
*/
//Output the HTML.
echo $tmpl->run(file_get_contents("html/index.html"));
?>

Categories