When ubercart is used in a service-based context with paid subscriptions to files, the bug comes into play when multiple users are registered.

If one paid user accesses their purchase and downloads the file (in say an arbitrary 50 download limit), this completely removes that same file access to all other paid users across the board. The file simply disappears on all the other user accounts.

I have reproduced this on clean installations on separate servers with varying versions.

This bug is reproducible with Drupal 6.8 & 6.9 and Ubercart 6.x-2.0-beta3 (and beta2).

CommentFileSizeAuthor
#7 uc_file.record.patch536 bytescha0s
#3 uc_files.patch796 bytesjody lynn

Comments

cha0s’s picture

Strange, I thought that could only happen if somehow they would have had the same file_key generated, but that's pretty unlikely (although I suppose, possible). I'll get this fixed very soon!

ibuprofen’s picture

Well actually, I've noticed that they don't have the same file_key. They are different which is why I've been scratching my head at this for awhile (I've made several attempts to fix this before I posted a bug report). Yet it STILL drops access to the same file across the other users' paid accounts as well.

If I can be of any assistance please let me know.

jody lynn’s picture

Priority: Normal » Critical
Status: Active » Needs review
StatusFileSize
new796 bytes

Really bad bug!

Untested fix attached.

jody lynn’s picture

Patch fixes the problem on our site.

jody lynn’s picture

After applying the patch I fixed our existing file orders by running the following php (I used batches of 100 orders and changed the WHERE statement each time):

$result = db_query_range("SELECT order_id FROM {uc_orders} WHERE order_id > 0 AND order_id < 100 ORDER BY order_id ASC ", 0, 100);
while ($id = db_result($result)) {
  $order = uc_order_load($id);
  $user_downloads = array();

  // Load user.
  if ($order->uid && ($order_user = user_load($order->uid))) {
    // Scan products for models matching downloads.
    foreach ($order->products as $product) {
      $files = db_query("SELECT * FROM {uc_file_products} AS fp ".
        "INNER JOIN {uc_product_features} AS pf ON pf.pfid = fp.pfid ".
        "INNER JOIN {uc_files} as f ON f.fid = fp.fid ".
        "WHERE nid = %d", $product->nid, $order_user->uid);

      while ($file = db_fetch_object($files)) {

        // Either they match, or the file was set to any SKU.
        if (!empty($file->model) && $file->model != $product->model) {
          continue;
        }

        // Grab any existing privilege so we can calculate the new expiration time
        // as an offset of the previous.
        $file_user = _uc_file_user_get($order_user, $file->fid);

        // Get the limit info from the product feature
        $file_modification = array(
          'download_limit' => uc_file_get_download_limit($file),
          'address_limit' => uc_file_get_address_limit($file),
          'expiration' => _uc_file_expiration_date(uc_file_get_time_limit($file), $file_user->expiration),
        );

        // Add file_user(s) for this file/directory. (No overwrite)
        $new_files = uc_file_user_renew($file->fid, $order_user, $file->pfid, $file_modification, FALSE);

        // Save for notification.
        $user_downloads = array_merge($user_downloads, $new_files);

      }
    }
  }
}
cha0s’s picture

Assigned: Unassigned » cha0s
Status: Needs review » Reviewed & tested by the community

Thanks a lot for that, Jody Lynn. The fix is correct, I can't believe that wasn't found until now...

cha0s’s picture

StatusFileSize
new536 bytes

I see now, the reason I didn't see a problem in my local is because I had the patch applied that I posted here: http://www.ubercart.org/files/uc_file.2.x.patch

I have attached a patch that is more appropriate.

yesct’s picture

I just, just, got the latest 2.x dev from bazar and it does not have this patch.

line 341 still reads:

  // Delete the old entry for this file.
  db_query("DELETE FROM {uc_file_users} WHERE fid = %d", $file_user->fid);

  drupal_write_record('uc_file_users', $file_user);

Did this patch still need to be committed?

rszrama’s picture

Yeah, hence the status. When it's committed, it'll be moved to fixed. ; )

Island Usurper’s picture

Status: Reviewed & tested by the community » Fixed

I know why this issue wasn't found for a while. It's really hard to think about testing how multiple users will affect things when you're only one person. ;) And that probably explains why I've taken so long to review this patch.

Committed now.

Status: Fixed » Closed (fixed)

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