Problem/Motivation

Using tokens under File name that may have slashes in them ('/') causes File (Field) Paths to create the subdirectories as provided by the token. If you have a file name with this token:

[node:title]-[file:ffp-name-only-original].[file:ffp-extension-original]

and create a node with the title "sub/dir" and upload a file name 'example.png' File (Field) Paths will then place the file in the following directory structure:

files/sub/dir-example.png

This is not the expected behavior when operating with the file name of a file, but as @Deciphered pointed out in #15 changing this might break existing installations.

Proposed resolution

Provide an option under both File path options and File name options that adds a special case for the path delimiter with a default vaule that won't break existing behavior, but will allow file names to reside in the directory they were configured.

Remaining tasks

Provide a working patch

User interface changes

An additional checkbox under both File path options and File name options that allows for special treatment of '/'.

API changes

None.

Original report by @pp

Original title: If token contains slash (/) module doesn't work correctly

How reproduce this bug:

  1. drush dl filefield_paths entity_api
  2. drush en filefield_paths entity_api entity_token
  3. Add a new vocabulary call test_vocabulary
  4. Add 3 term:
    term_1
    -term_2
    --term_3
    (term_2 parent of term_3, term_1 parent of term_2)
  5. Add a new content type call test
  6. Add a taxonomy term reference field call test_tax_ref
  7. Add file filed and set fielfield Path settings a following:
    [node:field-test_tax_ref:parents:join-path]
  8. Add a new test content. Set test_tax_ref to term_3. Upload a file, and save node.

The file path will be "term_1term_2/[filename]" instead of "term_1/term_2/[filename]"

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

pp’s picture

Assigned: pp » Unassigned
Status: Active » Needs review
FileSize
668 bytes

Here is the patch which resolve this issue.

Deciphered’s picture

Priority: Critical » Normal
Status: Needs review » Fixed

Thanks for the work, committed.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

kaare’s picture

Status: Closed (fixed) » Needs review
FileSize
709 bytes

It still doesn't work due to this in filefield_paths.module:383:

  // Process string tokens.
  $value = token_replace($value, $data, array('clear' => TRUE));

  $paths = explode('/', $value);
  foreach ($paths as $i => &$path) {
    …

Whenever a token e.g. [node:title] contains a '/', filefield_paths will create new folders according to node title, so if you have a node title "very/long/subdirectory", pathauto won't get a chance to clean this up and you end up with a very deep folder structure. I suspect you could do all kinds of wrong if you start using this for node title: "../../index.php" or worse. token_replace() needs to be run on each individual $path within the for-loop to make sure it's the folder structure the site admin has configured that will rule, rather than what an unknowing user inputs.

Folder separation should happen before token replacement, like this:

  $paths = explode('/', $value);
  foreach ($paths as $i => &$path) {

    // Process string tokens.
    $path = token_replace($path, $data, array('clear' => TRUE));
    …

Patch attached.

kaare’s picture

Nope. That wasn't enough. There is also this:

        $pathinfo = pathinfo($path);
        $path = str_replace($pathinfo['filename'], pathauto_cleanstring($pathinfo['filename']), $path);

So if [node:title] is "You Cant See Me/This Will Be Processed.ButNotThis", only "This Will Be Processed" will be sent to the cleaners. The replaced path will still have unprocessed parts of the file name with potential directory delimiters.

This new patch rebuilds the file name based on everything returned from pathinfo() and it also keeps #2047835: "Cleanup using Pathauto" Not Working Properly happy.

The question is whether users want to use tokens with an existing directory structure, but that would require additional configuration in the field form in the line of [ ] Keep directory structure from tokens. But I imagine this is a followup issue.

kaare’s picture

Aaand, pathinfo() sets 'dirname' to '.' when only file name is present which resulted in files starting with '.' (hidden). Added test for that too.

kaare’s picture

Steps to reproduce after clean install with 'standard' profile:

  1. Enable the filefield_path and pathauto modules
  2. Configure the 'field_image' field in the 'article' content type: admin/structure/types/manage/article/fields/field_image
  3. Under 'File (field) Path Settings' set 'File Name' to [node:title].[file:ffp-extension-original] and enable 'Cleanup using Pathauto' under 'File Name Options'.
  4. Create an article with title a/b/c/d and upload a random image.
  5. Observe that the image path now is .../files/images/a/b/c/d.jpg
  6. Apply patch in #6, repeat step 4 and observe the new path to be .../files/images/abcd.jpg, as expected.

This is kind of critical, so it would be nice if someone could confirm and/or review it.

Deciphered’s picture

@kaare,

Please note that this original issue is that the user wanted slashes in tokens not to be removed, and your issue is that you do want slashes in tokens to be removed. So what you see as a critical issue, others see as a feature, and therefore I am in a very difficult situation, to fix your issue I have to break things for others.

So what is the solution? I'm open to suggestions.

In the meantime, you could always make custom tokens that sanitize the node title as you see fit. Not ideal, but this issue does need further thought before it can proceed.

Deciphered’s picture

Also, this issue, and my last reply, inspired a new module; Rule Tokens.

It allows you to use a Rule component to process the value of a token creating a new token. So you could theoretically create a new token called something like [node:title:rule_tokens:rules_remove_slashes] that removed all slashes from the [node:title] token just using Rules for the logic.

kaare’s picture

Oh, I'm so sorry. Totally misinterpreted that. I totally see you being torn by this. '/' is the essence of this module, and how to interpret that when part of tokens is tough.

Though, my expectation on this is:

  • Tokens used in the file_name part should not be given a chance to change the directory structure. It's unexpected. You configure the file name and expect it to reside in the directory configured in file_path.
  • When ...['file_name']['options']['pathauto'] (Clean up using pathauto) is set, pathauto should orchestrate manipulation of the individual characters, including '/'. At least for file_name

So my suggestion would be to let tokens values orchestrate the directory structure in file_path, but not in file_name.

Deciphered’s picture

It is a very tricky situation indeed, I entirely see the logic in what you're saying, but I don't like making decisions that break things for others.

The correct way of tackling this issue is to make that logic configurable by the user, allow them to make that decision. That can be done with the Rule Token module I provided, at least for those willing to delve into Rules, and for the others, I will keep thinking on exactly what I want to do.

However, the plan for sometime now has actually been to rebuild FFP with Rules in a new module, and then make FFP a sub-module of the new module that provided the same existing functionality of FFP, the same interface, but used the new module as the engine, so maybe the Rule Token module may just be the way it's going to be.... I can't yet say.

alex.skrypnyk’s picture

@Deciphered
kaare's solution actually fixes the module to behave exactly how it is expected.

Pathauto should be cleaning up each tokenised value and then the rest of slashes should be used as path delimiters. I'm really struggling to understand how one would use this functionality otherwise (i.e. currently, if a token contains slash, the file is created in a folder).

alex.skrypnyk’s picture

Priority: Normal » Critical
Issue summary: View changes
Issue tags: +pathauo, +slash

Bumping this to critical since files get misplaced.

alex.skrypnyk’s picture

Provided patch addresses the issue in another way by processing each token separately in token replacement callback.

Deciphered’s picture

Category: Bug report » Feature request
Priority: Critical » Normal
Status: Needs review » Needs work

@alex.designworks,

Please refer to https://drupal.org/comment/7965831#comment-7965831, implementing this path will break things for other users. Until a solution can be determined that allows both usecases to be catered for I can not implement a change.

Also, that patch does not appear to be rolled from HEAD and reintroduces code that has been removed and is unrelated to this issue.

And lastly, this issue is not critical as currently this is works as designed and a feature request to support an alternate usecase, and there are workarounds currently available.

alex.skrypnyk’s picture

The initial patch https://drupal.org/files/1942720.patch works with replaced values instead of working with array of tokens=>values.

My patch uses callback that works with tokens=>values array directly. Although it does not have the logic to skip tokens that have ':join-path', it allows to add such logic to cover both cases _automatically_. This means that all occurrences of tokens with ':join-path' will continue having them replaced using native token module replacement mechanism; other tokens will have their values replaced using this module mechanism. In other words, the module will behave as expected, but will respect slashes in token values.

Also, the patch was rolled from 7.x. I'm not sure what other branch I should use.

rroblik’s picture

Ok so about 6 month after last post ...
Is there any working solution to avoid slash owner token create subdirectories ?
eg : "My famous post 24 / 24 is all the day" (files/my-famous-post-24/24.jpg)

Thanks

BWPanda’s picture

Title: If token contains slash (/) module doesn't work correctly » Provide option to allow removing slashes (/) from tokens
Status: Needs work » Needs review
Issue tags: -pathauto
FileSize
1.74 KB

This patch adds an option to remove slashes (/) from tokens. It then chooses when to processes string tokens based on that option.

Works for me. Review and see if this solves the above issues for everyone else.

kaare’s picture

Category: Feature request » Bug report
Priority: Normal » Major
Status: Needs review » Needs work

@BWPanda: Excellent idea to have an option for this. This will solve the dilemma between existing and expected behavior. Though this patch needs some work:

  • It doesn't work for any combination of Remove slashes … and Cleanup using Pathauto for both File path options and File name options. Using [node:title] as part of file name token and creating an article named "Sub/dir" still puts the image in .../sub/dir-<filename>.
  • Using pathauto (which is the only way this patch will ever clean up the file path), this code will only clean up the file name part of the path, as I pointed out in #5, meaning this setting will never bite.

@Deciphered: Please respect the severity of this issue. Messing with subdirs in a file name is a bug and a potential security issue.

kaare’s picture

Issue summary: View changes
kaare’s picture

There are some questions still:

  • Using pathauto to clean up, should Remove slashes actively remove them, or let pathauto take care of it? Or rather, let pathauto get the first attempt, then remove what's left?
  • The complexity in order to be backwards compatible in filefield_paths_process_string() is doubled. This should probably be split up.
kaare’s picture

Status: Needs work » Needs review
FileSize
3.31 KB

This is a working edition with backwards compatibility. It works by removing slashes after pathauto has called it a day, thereby letting the site admin use pathauto to select what character '/' should be replaced with.

kaare’s picture

The last patch is a combination of @BWPanda's work in #18 and the patch in #6.

aytee’s picture

Thank you kaare! This solution in #23 worked for me and was exactly what I needed.

cmseasy’s picture

#23 worked for me, thanks.
The bulk rename proces is also faster!

UksusoFF’s picture

Thx to kaare! Works like a charm.
Any way to hook cleanup rules for tokens?

UksusoFF’s picture

Anyone can update patch #23 for latest dev?

Deciphered’s picture

Issue tags: -slash +Needs tests

@UksusoFF,

No need for a re-roll, patch still applies to dev.

 

@kaare,

Thanks for the work, this meets all the requirements I had. I will be committing this at some point in the future (soon), but before I do so there does need to be some tests written. I will likely write them myself, but if you do feel so inclined, feel free to add them to the patch.

UksusoFF’s picture

@Deciphered
I've unsuccessful tried apply this patch on previous dev version. On current version from 2015-Sep-08 it's work great.

Deciphered’s picture

@UksusoFF,

'patch -p1 < [patch]', works perfectly for me, but if it doesn't work for you then I'd suggest waiting till it's committed.

UksusoFF’s picture

@Deciphered

On current version from 2015-Sep-08 it's work great.

Deciphered’s picture

Ah, misread. Good to hear.

Deciphered’s picture

Status: Needs review » Fixed

Thanks for the patience and patches. Committed and pushed.

  • Deciphered committed 5a7cd64 on 7.x-1.x
    #1942720 by Deciphered, kaare, alex.designworks, pp, BWPanda: Added...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.