How to pass a filename via URL? - php

I need to pass filenames via the url, e.g.:
http://example.com/images/niceplace.jpg
The problem I'm having is when the file name contains a blank character, e.g.:
http://example.com/images/nice place.jpg
or
http://example.com/images/nice%20place.jpg
For these two URLs, codeigniter complains about the blank char: "The URI you submitted has disallowed characters."
How should I go about fixing this?
I know I can add the blank character to the permitted_uri_chars in config.php but I'm looking for a better solution as there might be other disallowed characters in a filename.

I figured out a solution.
The URL is generated using rawurlencode().
Then, within the images controller, the filename is decoded using rawurldecode(html_entity_decode($filename)).
I successfully tested this solution with a few special characters I can think of and with UTF-8 characters.

You can use this method:
http://php.net/urlencode
Actually, you will run into another issues, when a filename would contain & character, and a few others. urlencode would get rid of all the possible issues.

This configuration option is created to avoid some characters being passed in URI and you want to walkaround it in some cases. I think most appropriate solutions are:
Pass file name as a parameter - http://domain.com/images/?image=test.jpg
Remove all non alfanumeric characters and may be some other (dash, underscore, etc) from file name when you save it. In my opinion, it is better, because you can face other problems with some character in other cases.

One of the better way to work with url's for specified condition is to encode/encrypt your url parameters using encryption/security class in order to maintain URL security:
$encrypt=$this->encrypt->encode($param1) & $this->encrypt->decode($encrypt)
Alternatively if you want special chars to be allowed in the URL then change your config settings in config.php file.
File Location: application/config/config.php
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';
Add all characters in right side that you want to be allowed with your application.

Related

Removing characters after last alpha character (if exist) in url in PHP

I'm redoing a website and on this website there are two types of URL such as:
http://www.example.com/category/subcategory/one-friend-url-040569485.php
http://www.example.com/category/subcategory/one-friend-url.php
I need to get only one-friend-url without the extension .php or -040569485.php in any of the above situations, so I can submit the one-friend-url to be searched in mySQL.
So if the URL does not have a -040569485.php it just removes the .php extension, otherwise removes the -040569485.php from the URL.
What would be the best way to do this (php, regex or .htaccess)?
Can you try the regex if you need it in the format between "subcategory/" and ".php" with the numbers as optional
"subcategory/(.*?)(?:-?\d*?)\.php"

laravel. Replace %20 in url

I have simple problem, I have to replace %20 and other crap from URL. At the moment it looks like this http://exmaple/profile/about/Eddies%20Plumbing. As you can see it's profile link.
Yes I could add str_replace values before every hyperlink, but I have like 10 of them and I think it's bad practice. Maybe there is better solution? What solution would you use? Thanks.
That is not crap, that is a valid unicode representation of a space character. And it's encoded because it's one of the characters that are deemed unsafe by RFC1738:
All unsafe characters must always be encoded within a URL. For
example, the character "#" must be encoded within URLs even in
systems that do not normally deal with fragment or anchor
identifiers, so that if the URL is copied into another system that
does use them, it will not be necessary to change the URL encoding.
So in order to have pretty URLs, you should avoid using reserved and unsafe characters which need encoding to be valid as part of a URL:
Reserved characters: $ & + , / : ; = ? #
Unsafe characters: Blank/empty space and < > # % { } | \ ^ ~ [ ] `
Instead replace spaces with dashes, which serve the same purpose visually while being a safe character, for example look at the Stack Overflow URL for this question. The URL below looks just fine and readable without spaces in it:
http://exmaple/profile/about/eddies-plumbing
You can use Laravel's str_slug helper function to do the hard work for your:
str_slug('Eddies Plumbing', '-'); // returns eddies-plumbing
The str_slug does more that replace spaces with dashes, it replaces multiple spaces with a single dash and also strips all non-alphanumeric characters, so there's no reliable way to decode it.
That being said, I wouldn't use that approach in the first place. There are two main ways I generally use to identify a database entry:
1. Via an ID
The route path definition would look like this in your case:
/profiles/about/{id}/{slug?} // real path "/profiles/about/1/eddies-plumbing"
The code used to identify the user would look like this User::find($id) (the slug parameter is not needed, it's just there to make the URL more readable, that's why I used the ? to make it optional).
2. Via a slug
The route path definition would look like this in your case:
/profiles/about/{slug} // real path "/profiles/about/eddies-plumbing"
In this case I always store the slug as a column in the users table because it's a property relevant to that user. So the retrieval process is very easy User::where('slug', $slug). Of course using str_slug to generate a valid slug when saving the user to the database. I usually like this approach better because it has the added benefit of allowing the slug to be whatever you want (not really needing to be generated from the user name). This can also allow users to choose their custom URL, and can also help with search engine optimisation.
The links are urlencoded. Use urldecode($profileLink); to decode them.
I am parsing the url tha i got in this way ->
$replacingTitle = str_replace('-',' ',$title);
<a href="example.com/category/{{ str_slug($article->title) }}/" />
In your view ...
{{$comm->title}
and in controller using parsing your url as
public function showBySlug($slug) {
$title = str_replace('-',' ',$slug);
$post = Community::where('title','=',$title)->first();
return view('show')->with(array(
'post' => $post,
));
}

Codeigniter disallowed characters workaround

I have already checked quite a few other answers but to no avail.
I have been hired to fix bugs for a job that some other developer ran away from.
The application has a add comment and delete comment functionality.
The problem comes in the delete comment part. He designed the database such that all comments are simply entered into a single cell separated by pipe characters. So while deleting a comment, the entire comment needs to be placed in the url as a parameter which is then passed to the model and removed from the database.
I do know this is bad, but I cannot recode the entire functionality.
Now, when a user enters a comment such as "What's Up?", the delete comment url throws the "Codeigniter: The URI you submitted has disallowed characters." error.
I tried converting the quotes to HTML character entities but they again contain disallowed characters.
Can anybody please suggest a possible workaround for this problem?
Redesigning the database is not a viable option as I'll then have to change the extensive php code used for handling the different delimiters.
Messing with the disallowed characters list also seems to be a bad idea.
Thank you.
Open your config file and find this parameter:
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_()#&-!=?';
You can change it according to your requirement ​or you can leave it blank.
Read the comment section in config file.
It says that: Leave blank to allow all characters -- but only if you are insane.
I am not sure if htmlentities will help.
Did you first call urlencode on just the parameters?
<?php
$query_string = 'foo=' . urlencode("What's Up?");
echo '<a href="mycgi?' . htmlentities($query_string) . '">';
?>
<a href="mycgi?foo=What%27s+Up%3F">
Also check if you need to add escape characters to any of these if they are treated as special characters by the database.
e.g. If % is treated as special character, then you may need to add a \ before it.

Urlencode forward slash 404 error

http://localhost/foo/profile/%26lt%3Bi%26gt%3Bmarco%26lt%3B%2Fi%26gt%3B
The url above gives me a 404 Error, the url code is this: urlencode(htmlspecialchars($foo));, as for the $foo: <i>badhtml</i>
The url works fine when there's nothing to encode e.g. marco.
Thanks. =D
Update: I'm supposed to capture the segment in the encoded part of the uri, so a 404 isn't supposed to appear.
There isn't any document there, marco is simply the string that I needed to fetch that person's info from db. If the user doesn't exist, it won't throw that ugly error anyways.
Slight idea what's wrong: I found out that if I used <i>badhtml<i>, it works just fine but <i>badhtml</i> won't, what do I do so that I can maintain the / in the <i>?
It probably think of the request as http://localhost/foo/profile/<i>badhtml<**/**i>
Since there is a slash / in the parameter, this is getting interpreted as a path name separator.
The solution, therefore, is to replace all occurrences of a slash with something that doesn't get interpreted as a separator. \u2044 or something. And when reading the parameter back in, change all \u2044s back to normal slashes.
(I chose \u2044 because this character looks remarkably like a normal slash, but you can use anthing that would never occur in the parameter, of course.)
It is most likely that the regex responsible for handling the URL rewrite does not like some of the characters in the URL-encoded string. This is most likely httpd/apache question, rather than PHP. Your best guess is to start by looking at the .htaccess (file containing URL rewrite rules).
This question assumes that your are trying to pass an argument through the URL, rather than access a file named <i>badhtml</i>.
Mr. Lister, you rocked.
"The solution, therefore, is to replace all occurrences of a slash with something that doesn't get interpreted as a separator. \u2044 or something. And when reading the parameter back in, change all \u2044s back to normal slashes."

Optional regular expression segment, but list of requirements if present?

I have a small routing engine in PHP. I'm trying to allow it to optionally match different "formats", such as requests to "/user/profile.json" or "/user/profile.xml". However, it should also match just a plain "/user/profile".
So, if if the format is present, it must be ".json" or ".xml". But it isn't required to be present at all.
Here is what I have so far:
#^GET /something/([a-zA-Z0-9\.\-_]+)(\.(html|json))?$#
Obviously, this doesn't work. This allows any "format" to be requested since the entire format segment is optional. How can I keep it optional, but constrain the formats that can be requested?
^GET /something/([a-zA-Z0-9._-]+)(\.(html|json))?$
allows dots in the first character class, so any file extension is legal. I expect you did that on purpose so filenames with dots in them are possible.
However, this means that if a filename contains a dot, it must end in either .html or .json. Right?
So change the regex to (using the \w shorthand for [A-Za-z0-9_]):
^GET /something/([\w.-]+\.(html|json)|[\w-]+)$
Alternative suggestion:
Instead of putting the desired output format into the URL, have the client specify it via the Accept Header in the HTTP Request (where it belongs). Content negotiation is baked into the HTTP protocol, so you do not have to reinvent it via URLs. Technically, it is wrong to put the format into the URL. Your URIs should point to the resource itself and not the resource representation.
Also see W3C: Content Negotiation: why it is useful, and how to make it work
The issue you're getting is arising from the fact that most extensions are alpha numeric, yet in your regex you're allowing a dot and characters:
#^GET /something/[a-zA-Z0-9\.\-_]+(\.(html|json))?$#
The section of problem being [a-zA-Z0-9\.\-_]+. For the example of the .csv making it though is because it's still matching that character range.
If something has dots in it's file name, then by default, it has a file extension (intentional or unintentional). The file My.Finance.Documents has the extension ".Documents" even though you'd assume it to be a text file or something else.
I hate doing it, but I think you might want to have a larger conditional in your regex, something along the lines of (this is an example, I haven't tested it):
#^GET /something/([^\.]+|.*\.(?:html|json))$#
Basically, if the file name has not dots in it, it's ok. If it does have a dot in it (which guarantees it has an extension), it must end with .html or .json.

Categories