This module provides a way to hide absolute paths to files from the
page source, even if your Drupal instance is using the Public download method.
For example, when an anonymous user clicks on a file path altered
by Hide Filepah, they're asked to login first and then redirected to the file.
It especially comes in handy if you want users to be prompted to login first
before viewing or downloading files. You can show them
an access denied, or 404 page. There's also the option for a module developer
to hook into the processes and do their own thing.

Note: This is not a security module since you can still hit the direct file path and gain access if you can construct the path manually. But it does play a little off of "security through obscurity".

Hide Filepath Sandbox Project page

Git
git clone --branch 7.x-1.x git.drupal.org:sandbox/eriknewby/1861422.git

Project Reviews:
http://drupal.org/node/1976534#comment-7338482
http://drupal.org/node/1510564#comment-7333654
http://drupal.org/node/1266460#comment-7333630
http://drupal.org/node/1998762#comment-7434058
http://drupal.org/node/1995434#comment-7433670
http://drupal.org/node/1982026#comment-7433694

Comments

PA robot’s picture

We are currently quite busy with all the project applications and we prefer projects with a review bonus. Please help reviewing and we will take a look at your project right away :-)

Also, you should get your friends, colleagues or other community members involved to review this application. Let them go through the review checklist and post a comment that sets this issue to "needs work" (they found some problems with the project) or "reviewed & tested by the community" (they found no major flaws).

I'm a robot and this is an automated message from Project Applications Scraper.

tmctighe’s picture

Status: Needs review » Needs work

Erik,

The module installed, configured, and worked simple and easy. The video helps to easily understand!

1. This module has a couple minor pareview errors: (http://ventral.org/pareview/httpgitdrupalorgsandboxeriknewby1861422git)

  • Remove LICENSE.txt, it will be added by drupal.org packaging automatically.
  • Remove "version" from the ./hide_filepath.info file, it will be added by drupal.org packaging automatically.
  • Remove "project" from the ./hide_filepath.info file, it will be added by drupal.org packaging automatically.

2. Coding standards: A couple points:

In hide_filepath.install you initiate variables however do not implement a hook_uninstall to remove those variables.
Also, the db_query should be changed to a db_update (see: http://api.drupal.org/api/drupal/includes%21database%21database.inc/func...)

3. The module appears to support image fields and the video module - it would be good to list this on the Project page. In general, separating that first paragraph on the project page into sections "Use Case Scenario" and "Features" might help users understand what the module does.

(Also, the functionality for hiding videos did not work for me on a clean installation.)

Otherwise the module looks good!

eriknewby’s picture

Status: Needs work » Needs review

Thanks for reviewing tmctighe.

Updated:

  1. Removed LICENSE.txt
  2. Removed version and project from .info
  3. Added hook_uninstall to remove variables
  4. Changed db_query to db_update

Will also update the project page.
As for supporting the video module, though some of the code is in place, I haven't documented it yet since I would like to treat that as a second release feature.
Given that, I may pull it out of the branch and place it in a separate dev branch.

pranit84’s picture

Status: Needs review » Needs work

FILE: /var/www/drupal-7-pareview/pareview_temp/hide_filepath.install
--------------------------------------------------------------------------------
FOUND 1 ERROR(S) AFFECTING 1 LINE(S)
--------------------------------------------------------------------------------
29 | ERROR | Missing function doc comment
--------------------------------------------------------------------------------

eriknewby’s picture

Thanks pranit84.
I've fixed the function doc comment.

eriknewby’s picture

Status: Needs work » Needs review
eriknewby’s picture

Issue summary: View changes

updated wording, and added branch to git repo

eriknewby’s picture

Issue summary: View changes

adding project reviews

eriknewby’s picture

Assigned: Unassigned » eriknewby
Issue tags: +PAreview: review bonus

adding review bonus

klausi’s picture

Status: Needs review » Needs work
Issue tags: -PAreview: review bonus

manual review:

  1. I'm a bit confused by the purpose of this module. I could just use private files supported by Drupal core instead? Also I think you should add a big fat note to your project page that this module does not protect the actual files in any way. If a user knows the path to a file she can access it without any protection and she can share that link with others. So your module does not provide any real security.
  2. hide_filepath_install(): do not juggle with module weights, that is unreliable. Use hook_module_implements_alter() if you need to run before/after a specific hook.
  3. hide_filepath_install(): No need to set variables upon installation as you can make use of default values with variable_get() anyway.
  4. hide_filepath_init(): so your module only works with nodes and not with fields on other entity types? Please add that to the README.txt and the project page.
  5. hide_filepath_init(): "$function = $module . '_hide_filepath_pre_validation';": that function is not invoked on the next line, your are kust assigning a variable.
  6. "module_implements('hide_filepath_pre_validation')": Hooks that are provided by a module should be documented in MODULENAME.api.php, see http://drupal.org/node/161085#api_php
  7. hide_filepath_init(): what is all this hacking around with arg()? Why can't you register a proper path with hook_menu()? Also hook_init() is called on every single page request, so that big function will slow down your site considerably.
  8. "$field['und']": do not use "und", use LANGAUGE_NONE instead.
  9. "$file_path = check_plain(file_create_url($file->uri));": why do you call check_plain() here? The URL is never printed to the user? And the created file URL is not untrusted user provided input? Please read http://drupal.org/node/28984
  10. hide_filepath_settings_page(): that function can be removed, just use drupal_get_form as page callback in hook_menu() to directly invoke the form builder.
  11. hide_filepath_settings_validate(): empty function, so remove it.
  12. hide_filepath_settings_submit(): that function can be removed if you use system_settings_form() in hide_filepath_settings().

Removing review bonus tag, you can add it again if you have done another 3 reviews of other projects.

eriknewby’s picture

Excellent! Thank you so much for the valuable and helpful feedback, klausi
I will report back soon once I've had a chance to rework these items.

FYI, this is definitely not meant to be a security module. Simply to provide a little obfuscation to file paths and provide the admin a few configurable options.
Since my description may have been unclear, I will make sure that is clearly stated on the project page.

Thanks again!

eriknewby’s picture

Status: Needs work » Needs review

I've finally had some time to make some updates to the module based on klausi's feedback.

1. Added a disclaimer to the README and project page about this *not* being an actual security module
2. removed juggling of module waits in favor of hook_module_implements_alter()
3. Added note that currently "node" is the only supported entity.
4. Added module_api file
5. Replace "und" with LANGUAGE_NONE
6. Removed unnecessary check_plain()
7. updated form to use drupal_get_form and directly invoke form builder
8. removed empty function hide_filepath_settings_validate()

ayesh’s picture

Some minor suggestions:

In hide_filepath.install:18 : It's better if you use the a tag in the t() function. This makes is less confusing to translators.
Ex:

drupal_set_message($t("Hide Filepath settings are available under <a href="@hide-filepath-admin">Administer > Site configuration > Hide Filepath</a>",
 array('@hide-filepath-admin' => url('admin/config/media/hide_filepath/settings'))
));

Using the a tag directly makes it much easier to translate the string, and that's the recommended way (There was a doc file describing it but couldn't find it yet).

hide_filepath.module:38: You are implementing hook_form_FORM_ID_alter.

hide_filepath.module:180: UID is an integer.

hide_filepath_settings.inc: Is there any reason why you didn't use system_settings_form() ?

eriknewby’s picture

@Ayesh,

Thanks! That tag based url in t() is new to me. Cool! I've added it.
Fixed the function comment
Fixed the integer in the if statement.

Could you elaborate on why/how to use system_settings_form()? I'd be happy to, I just don't think I understand what I did vs. what you are suggesting.
Thanks again!

nsuit’s picture

Status: Needs review » Needs work

I enabled your module, set the settings to "Access denied for Anonymous" users, but when I as anonymous clicked on the file link in my node it still loaded the file. Let me know if I misunderstood the purpose of the module.

Minor issue, Code_sniffer found two space issues.
FILE: .../nathalie/Sites/drupal-7.20/modules/hide_filepath/hide_filepath.install
--------------------------------------------------------------------------------
FOUND 2 ERROR(S) AFFECTING 2 LINE(S)
--------------------------------------------------------------------------------
20 | ERROR | Line indented incorrectly; expected 2 spaces, found 1
21 | ERROR | Line indented incorrectly; expected 2 spaces, found 0
--------------------------------------------------------------------------------

eriknewby’s picture

Hey nsuit,
Thanks for taking a look. I've fixed the indentation issue you listed.

As for your Anonymous access issue, did you have a chance to look through the README? I'm specifically wondering if you missed this step:

* When creating a file field on a content type, enable the "Hide Filepath"
checkbox when editing the file field properties.

Without that step, any and all file fields will continue to function as normal.

eriknewby’s picture

Status: Needs work » Needs review
ayesh’s picture

Could you elaborate on why/how to use system_settings_form()? I'd be happy to, I just don't think I understand what I did vs. what you are suggesting.

What I mentioned was actually to make use of the system_settings_form() function from core, that adds the proper "Save configuration" button and does the variable_set part for you.

Change return $form; with return system_settigns_form($form);.
This will add a submit button and a handler that saves values using variable_set. Variable names are taken from the $form_state['values'] array (thus, the key from the $form array).

This is all you need in the hide_filepath_settings.inc:

function hide_filepath_settings($form, &$form_state) {
  $form = array();
  $form['hide_filepath_anonymous'] = array(
    '#type' => 'select',
    '#title' => t('Anonymous User'),
    '#description' => t('Choose what an Anonymous User should receive when clicking a file path.'),
    '#options' => array(
      '403' => t('Access Denied'),
      '404' => t('Page Not Found'),
      'login' => t('Login challenge'),
      'custom' => t('Use custom hook'),
      'bypass' => t('Allow Normal Access'),
    ),
    '#default_value' => variable_get('hide_filepath_anonymous', 'login'),
    '#required' => TRUE,
  );

  $form['hide_filepath_authenticated'] = array(
    '#type' => 'select',
    '#title' => t('Authenticated User'),
    '#description' => t('Choose what an Authenticated User should receive when clicking a file path.'),
    '#options' => array(
      '403' => t('Access Denied'),
      '404' => t('Page Not Found'),
      'custom' => t('Use custom hook'),
      'bypass' => t('Allow Normal Access'),
    ),
    '#default_value' => variable_get('hide_filepath_authenticated', 'bypass'),
    '#required' => TRUE,
  );

  return system_settings_form($form);
}

You don't need to add a submit button and/or a submit handler.
Also pay attention to the variable_get() call, that we have a second parameter which returns in case the value is not set. variable_get function requires parameters by default - the variable name and a value to return in case the value is not set already.

Module worked well for me, and really nice work there. Good luck!

eriknewby’s picture

Excellent explanation, @Ayesh! Thanks for taking the time. Much appreciated.
I've updated the .inc with system_settigns_form(); and will use this approach from here on out in other projects as well :)

eriknewby’s picture

Issue summary: View changes

adding review

eriknewby’s picture

Issue summary: View changes

adding more project reviews to topic (also listed in comments)

jared_sprague’s picture

Nice work Erik! This looks RTBC to me!

klausi’s picture

Assigned: eriknewby » klausi
klausi’s picture

Assigned: klausi » cubeinspire
Status: Needs review » Reviewed & tested by the community
Issue tags: -PAreview: review bonus

Performed a manual code walkthrough with Erik here at Drupalcon, no critical blockers left.

manual review:

  1. hide_filepath_api.module: should be hide_filepath_api.php. And should contain examples.
  2. Take a look at your exit calls, they might not be needed.
  3. you could use module_invoke_all() to call your hooks.
  4. another check_plain() call that is not necessary.
  5. hide_filepath_settings(): wrong doc block, see http://drupal.org/node/1354#functions

Removing review bonus tag, you can add it again if you have done another 3 reviews of other projects.

Assigning to cubeinspire as he might have time to take a final look at this.

eriknewby’s picture

After speaking with klausi at Drupalcon Portland, I've updated the following per his suggestions
1. Removed the nasty hook_init() hacking and replaced with a clean hook_menu() :)
2. Fixed the naming of hide_filepath_api.php (examples will be added at a later time)
3. Removed check_plains and exits: that were unnecessary

Number one was the most important here. This makes sure hide_filepath actually gets called on pages where its needed, rather than every single page.
Thanks again klausi.

klausi’s picture

Status: Reviewed & tested by the community » Fixed

no objections for more than a week, so ...

Thanks for your contribution, eriknewby!

I updated your account to let you promote this to a full project and also create new projects as either a sandbox or a "full" project.

Here are some recommended readings to help with excellent maintainership:

You can find lots more contributors chatting on IRC in #drupal-contribute. So, come hang out and get involved!

Thanks, also, for your patience with the review process. Anyone is welcome to participate in the review process. Please consider reviewing other projects that are pending review. I encourage you to learn more about that process and join the group of reviewers.

Thanks to the dedicated reviewer(s) as well.

Status: Fixed » Closed (fixed)

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

Anonymous’s picture

Issue summary: View changes

updating description to include "note"