1

Our current system saves files that match the name of their parent group. So a group named "My Devices" saves an image called "My+Devices.jpg". This worked great, and even though there was some trouble with the name getting converted somewhere along the line of PHP and JS to "My%20Devices.jpg", I was able to just convert spaces to plus signs before that happened.

Now we need to account for other special characters, like apostrophes so that a group can be named "Joe's Devices". I need some way to convert that to something that can be a file name. BUT I can't just strip out the special characters or there could be a collision if someone uses a group name of "Joes Devices" (without the apostrophe).

I tried urlencode() and rawurlencode(), but those use percent signs, which are great for URLs but not so much for file names. I thought base64_encode() would be better even though it's a much longer string. But it includes equal signs which are no good for filenames.

Is there a way to convert a string to a filename-friendly string, one that can be decoded back to it's original string? Or do I need to recode this feature completely and use an ID match or something?

SpaceNinja
  • 496
  • 7
  • 20

2 Answers2

3

Your quest is very similar to questions around creating url-safe base64 encoded strings.

See this answer for one example: https://stackoverflow.com/a/5835352/660694

My solution would be a variation of this.

In one of my apps I have this wrapper function:

function base64_safe_encode($input, $stripPadding = false)
{
    $encoded = strtr(base64_encode($input), '+/=', '-_~');

    return ($stripPadding) ? str_replace("~","",$encoded) : $encoded;
}

Now you can generate a filename or url safe base64 encoded string that is easily reversible.

Note there is an option to strip the padding at the end of the string if you like, PHP does not require the padding characters to be present when you decode.

The decode function is then quite simple:

function base64_safe_decode($input)
{
    return base64_decode(strtr($input, '-_~', '+/='));
}
Community
  • 1
  • 1
jszobody
  • 28,495
  • 6
  • 61
  • 72
1

Lets say you have a group named 'My Device'. You then hash the name of it with md5 to save it in a database or something:

$group = 'My Device';
$filename = md5($group) . '.png';

To display or work with it, you just hash the group name again wherever you want:

<?php
$group = 'My Device';
$filename = md5($group) . '.png';
?>
<img src="<?php print $filename; ?>" />
Manuel Mannhardt
  • 2,191
  • 1
  • 17
  • 23
  • 1
    But given the hash you can't get `My Device` is the OP's point. – AbraCadaver Oct 06 '16 at 20:32
  • 1
    I see now. But why not save `My Device` in a database or textfile so he can work with the value based on the "ID" and maybe save the hash with it? At least it would be a workaround to not have to have weird symbols in filenames. – Manuel Mannhardt Oct 06 '16 at 20:35
  • I'm trying to make this fix as small as possible and not have to re-write how it was done originally if I can. But that's a good idea if I do have to refactor this. – SpaceNinja Oct 06 '16 at 20:37
  • 1
    Another way could be (even tho I dont think its very practicable) to convert the characters into their ASCII values and save it like 12_34_45_12. You can easily seperate them and "decode" them back. – Manuel Mannhardt Oct 06 '16 at 20:40