Laravel combining routes - php

Is there any way of combining these two following routes?
Route::get('project/(:any)', 'dashboard.project#(:1)');
Route::get('project/(:any)/(:any)', 'dashboard.project#(:1)');
I'm asking because the second route, I had to add it in order for the following requests to work:
site.com/project/new => method
site.com/project/view/12351326 => method and parameter

You can use regex in the first parameter of the get() method to combine those.
See section Regular Expression Route Constraints in the docs.
Something like this might work:
Route::get('project/{name}', function($name)
{
//
})
->where('name', '[A-Za-z0-9\/]+');
Where the regex will match URLs such as /projects/something/anything. However that might be too loose - it will also match /projects/any/number/of/url/segments. But I believe some more RegEx can help make better constraints to get closer to what you're looking for.

Related

How to apply regex to check route param is in array

I have route like this. I am trying to check if route param social is either facebook, google or twitter.
Route::get('/login/{social}', 'Auth\LoginController#loginSocial')
->where('social',["facebbok","google","twitter"]);
Above route is not working. It asks for regex. Please help.
How to check this ?
Try this:
Route::get('/login/{social}', 'Auth\LoginController#loginSocial')
->where('social','(facebook|google|twitter)');
The where method on a route instance accepts the name of the parameter and a regular expression, your second parameter isn't a regular expression:
Route::get('/login/{social}', 'Auth\LoginController#loginSocial')
->where('social','(facebook|google|twitter)');
Here is a valid RegExp
You haven't stated what the method signature of the ->where but at a guess:
Route::get('/login/{social}', 'Auth\LoginController#loginSocial')
->where('social', "/^(facebook|google|twitter)$/i");
Hope this condition will helpful for you.
Route::get('/login/{social}','Auth\LoginController#loginSocial')
->where('social', 'facebook|google|twitter');

Laravel interpreting a string in route as parameter

I tried googling, but I can't phrase the question right, it is simple.
I have these 2 routes:
Route::get('admin_firme/{id_firma}/filijale/{id_filijala}', 'FilijalaAdminController#show');
Route::get('admin_firme/{id_firma}/filijale/create', 'FilijalaAdminController#create')
They call different controller actions. The problem is in the second route which calls the create method. The part /filijale/create is being interpreted as the parameter of the first route, thus calling the wrong method. How can I correct this?
I tried naming the route and generating an url to it, but it still calls the wrong method.
Just take the bottom one up ...
Route::get('admin_firme/{id_firma}/filijale/create', 'FilijalaAdminController#create');
Route::get('admin_firme/{id_firma}/filijale/{id_filijala}', 'FilijalaAdminController#show');
should work.
There's two things you can do. The first, and easiest, is to swap the order of them round so when checking matching routes it checks to see if it's create first, and if not anything else matches id_filijala.
The second thing you can do is use pattern matching for id_filijala, for example if it only contained numbers then you could use:
Route::get('admin_firme/{id_firma}/filijale/{id_filijala}', 'FilijalaAdminController#show')
->where('id_filijala', '[0-9]+');
You can use any regular expression in the where.

Converting pseudocode into usable (using regular expression?)

As part of the system I am writing, users can create their own custom Rules, to be run when certain events happen.
There are a set number of Objects they can use to create these rules, all of which have a set number of properties and methods:
So as an example of a rule, we could say:
“if this unit award is ‘Distinction’ then set all the criteria on this unit to award ‘Achieved’”
IF UNIT.award equals “Distinction”
THEN UNIT.criteria.set_award(‘A’)
“else if this unit award is ‘Merit’ then set the award of any criteria on this unit whose name starts with either ‘P’ or ‘M’ to ‘Achieved’”
IF UNIT.award equals “Merit”
THEN UNIT.criteria.filter(‘starts’, ‘name’, ‘P’, ‘M’).set_award(‘A’)
“else if this unit award is ‘Pass then set the award of any criteria on this unit whose name starts with ‘P’ to ‘Achieved’”
IF UNIT.award equals “Merit”
THEN UNIT.criteria.filter(‘starts’, ‘name’, ‘P’).set_award(‘A’)
The problem I am having, is I am just not sure how to take that string of object, properties & methods, e.g. “UNIT.criteria.filter(‘starts’, ‘name’, ‘P’).set_award(‘A’)” and convert it into something usable.
The end result I’d like to convert the string to would be something along the lines of:
So I can then convert that into the actual proper objects and return the relevant values or run the relevant methods.
Since there is only a set number of things I need to support (for now at least) and I don’t need anything complex like calculation support or variables, it seems overkill to create a Lexer system, so I was thinking of just using a regular expression to split all the sections.
So using the examples above, I could do a simple split on the “.” character, but if that character is used in a method parameter, e.g. “CRITERION.filter(‘is’, ‘name’, ‘P.1’)” then that screws it up completely.
I could use a less common character to split them, for example a double colon or something “::” but if for whatever reason someone puts that into a parameter it will still cause the same problem. I’ve tried creating a regular expression that splits on the character, only if it’s not between quotes, but I haven’t been able to get it to work.
So basically my question is: would a regular expression be the best way to do this? (If so, could anyone help me with getting it to ignore the specified character if it’s in a method). Or is there another way I could do this that would be easier/better?
Thanks.
I'd think an ORM language like eloquent could do this for you.
But if I had to do this then first I'd split the IF THEN ELSE parts.
Leaving:
UNIT.award equals “Distinction”
UNIT.criteria.filter(‘starts’, ‘name’, ‘P’, ‘M’).set_award(‘A’)
I'm guessing the "equals" could also be "not equals" or "greater" so...
I'd split the first bit around that.
/(?'ident'[a-z.]*?) (?'expression'equals|greater) (?'compare'[0-9a-z\“\”]+)/gi
But an explode around 'equals' will do the same.
Then I'd explode the second part around the dots.
Giving:
UNIT
criteria
filter(a,b,c,d)
set_ward(e)
Pop off the first 2 to get object and property and then a list of possible filters and actions.
But frankly I'd would develop a language that would not mix properties with actions and filters.
Something like:
IF object.prop EQUALS const|var
THEN UPDATE object.prop
WITH const|var [WHERE object.prop filter const|var [AND|OR const|var]]
Eloquent does it straight in php:
DB::table('users')
->where('id', 1)
->update(['votes' => 1]);
So maybe I'd do something like:
THEN object.prop->filter(a,b,c,d)->set('award','A')
This makes it easy to split actions around -> and properties around .
Anyway...
I do my Regex on https://regex101.com/
Hope this helps.

Codeigniter Routes, unexpected behavior and don't know why

So, I don't know how many times I have done similar with code igniter in the past across a handful of sites. However, just getting myself a fresh copy, and starting a rebuild on a new site Im already running into a twisted little issue that I can't figure out, I don't know what I am missing in this equation..
So this is my Routes currently:
$route['default_controller'] = "home";
$route['404_override'] = 'home/unknown';
$route['post/(:any)/(:any)'] = 'post/$1/$2';
//$route['post/(:any)'] = 'post/$1';
//$route['post'] = 'post';
$route['host-hotel'] = 'host_hotel';
$route['floor-plan'] = 'floor_plan';
$route['wine-facts'] = 'wine_facts';
$route['exhibitor-application'] = 'exhibitor_application';
$route['photo-gallery'] = 'photo_gallery';
$route['video-gallery'] = 'video_gallery';
Now the problem is specifically with this guy.
$route['post/(:any)/(:any)'] = 'post/$1/$2';
I've even tried naming the segment article instead of post, thinking maybe its a protected name of sorts in CI. If you notice above this line I have also tried adding varations of the URL so it could handle either just the first segment or one or two more there after. Grant it they are commented out in this example, but didn't work.
If I go to the domain.com/post the behavior is as expected. Anything there after is where the issue starts. If I did anything number or letter or combo there of..
ie: domain.com/post/s2hj or domain.com/post/s2hj/avd the page starts acting like the 404 behavior, page not found which to me makes no sense, as I said Ive done routes like this in the past. And to me this route looks proper? So anyone have any ideas/suggests what to look for?
:any matches literally any character, including slashes. This will be changed in CodeIgniter 3.0, but for the time being you can use ([^/]) to catch a single segment.
Another way to try this is through Good ol' regexp:
$route['post/([^/]+)/([^/]+)'] = 'post/$1/$2';
If also you need to be able to handle a total of 2 uri segments, consider:
$route['post/([^/]+)(?:/([^/]+))'] = 'post/$1/$2';
REGEXP explained:
() simply captures and handles the strings inside. Also gives us $1, $2 etc at the other end.
(?:) is the same as above, but doesn't capture $1
[] is the allowed combination of things inside. [0-9] will look for numbers only.
[^] is the reversed logic. everything exepct the given signs.
[^/] is everything but /, thus giving us desired result.

PHP - securing parameters passed in the URL

I have an application which makes decisions based on part of URL:
if ( isset($this->params['url']['url']) ) {
$url = $this->params['url']['url'];
$url = explode('/',$url);
$id = $this->Provider->getProviderID($url[0]);
$this->providerName = $url[0]; //set the provider name
return $id;
}
This happens to be in a cake app so $this->params['url'] contains an element of URL. I then use the element of the URL so decide which data to use in the rest of my app. My question is...
whats the best way to secure this input so that people can't pass in anything nasty?
thanks,
Other comments here are correct, in AppController's beforeFilter validate the provider against the providers in your db.
However, if all URLs should be prefixed with a provider string, you are going about extracting it from the URL the wrong way by looking in $this->params['url'].
This kind of problem is exactly what the router class, and it's ability to pass params to an action is for. Check out the manual page in the cookbook http://book.cakephp.org/view/46/Routes-Configuration. You might try something like:
Router::connect('/:provider/:controller/:action');
You'll also see in the manual the ability to validate the provider param in the route itself by a regex - if you have a small definite list of known providers, you can hard code these in the route regex.
By setting up a route that captures this part of the URL it becomes instantly available in $this->params['provider'], but even better than that is the fact that the html helper link() method automatically builds correctly formatted URLs, e.g.
$html->link('label', array(
'controller' => 'xxx',
'action' => 'yyy',
'provider' => 'zzz'
));
This returns a link like /zzz/xxx/yyy
What are valid provider names? Test if the URL parameter is one, otherwise reject it.
Hopefully you're aware that there is absolutely no way to prevent the user from submitting absolutely anything, including provider names they're not supposed to use.
I'd re-iterate Karsten's comment: define "anything nasty"
What are you expecting the parameter to be? If you're expecting it to be a URL, use a regex to validate URLs. If you're expecting an integer, cast it to an integer. Same goes for a float, boolean, etc.
These PHP functions might be helpful though:
www.php.net/strip_tags
www.php.net/ctype_alpha
the parameter will be a providername - alphanumeric string. i think the answer is basically to to use ctype_alpha() in combination with a check that the providername is a valid one, based on other application logic.
thanks for the replies
Also, if you have a known set of allowable URLs, a good idea is to whitelist those allowed URLs. You could even do that dynamically by having a DB table that contains the allowed URLs -- pull that from the database, make a comparison to the URL parameter passed. Alternatively, you could whitelist patterns (say you have allowed domains that can be passed, but the rest of the url changes... You can whitelist the domain and/ or use regexps to determine validity).
At the very least, make sure you use strip_tags, or the built-in mysql escape sequences (if using PHP5, parameterizing your SQL queries solves these problems).
It would be more cake-like to use the Sanitize class. In this case Sanitize::escape() or Sanitize::paranoid() seem appropriate.

Categories