From 2c45f6851e032f60d109ef3b3d368a5f0050b476 Mon Sep 17 00:00:00 2001
From: Micah Lee <micah@micahflee.com>
Date: Thu, 25 Oct 2018 21:13:16 -0700
Subject: [PATCH] Receive mode puts files in a directory based on the timestamp
 of the upload

---
 onionshare/__init__.py           |  2 +-
 onionshare/common.py             | 27 ---------------------------
 onionshare/web/receive_mode.py   | 27 ++++++++++++++-------------
 onionshare/web/web.py            |  1 -
 onionshare_gui/onionshare_gui.py |  5 +----
 share/locale/en.json             |  1 -
 6 files changed, 16 insertions(+), 47 deletions(-)

diff --git a/onionshare/__init__.py b/onionshare/__init__.py
index 069559c5..1e81333e 100644
--- a/onionshare/__init__.py
+++ b/onionshare/__init__.py
@@ -21,7 +21,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 import os, sys, time, argparse, threading
 
 from . import strings
-from .common import Common, DownloadsDirErrorCannotCreate, DownloadsDirErrorNotWritable
+from .common import Common
 from .web import Web
 from .onion import *
 from .onionshare import OnionShare
diff --git a/onionshare/common.py b/onionshare/common.py
index cab1e747..ffa6529f 100644
--- a/onionshare/common.py
+++ b/onionshare/common.py
@@ -32,20 +32,6 @@ import time
 from .settings import Settings
 
 
-class DownloadsDirErrorCannotCreate(Exception):
-    """
-    Error creating the downloads dir (~/OnionShare by default).
-    """
-    pass
-
-
-class DownloadsDirErrorNotWritable(Exception):
-    """
-    Downloads dir is not writable.
-    """
-    pass
-
-
 class Common(object):
     """
     The Common object is shared amongst all parts of OnionShare.
@@ -390,19 +376,6 @@ class Common(object):
                 }"""
         }
 
-    def validate_downloads_dir(self):
-        """
-        Validate that downloads_dir exists, and create it if it doesn't
-        """
-        if not os.path.isdir(self.settings.get('downloads_dir')):
-            try:
-                os.mkdir(self.settings.get('downloads_dir'), 0o700)
-            except:
-                raise DownloadsDirErrorCannotCreate
-
-        if not os.access(self.settings.get('downloads_dir'), os.W_OK):
-            raise DownloadsDirErrorNotWritable
-
     @staticmethod
     def random_string(num_bytes, output_len=None):
         """
diff --git a/onionshare/web/receive_mode.py b/onionshare/web/receive_mode.py
index 4a6934a1..66e00240 100644
--- a/onionshare/web/receive_mode.py
+++ b/onionshare/web/receive_mode.py
@@ -4,7 +4,6 @@ from datetime import datetime
 from flask import Request, request, render_template, make_response, flash, redirect
 from werkzeug.utils import secure_filename
 
-from ..common import DownloadsDirErrorCannotCreate, DownloadsDirErrorNotWritable
 from .. import strings
 
 
@@ -59,17 +58,19 @@ class ReceiveModeWeb(object):
             """
             Upload files.
             """
-            # Make sure downloads_dir exists
+            # Make sure the receive mode dir exists
+            now = datetime.now()
+            date_dir = now.strftime("%Y-%m-%d")
+            time_dir = now.strftime("%H.%M:%S")
+            receive_mode_dir = os.path.join(self.common.settings.get('downloads_dir'), date_dir, time_dir)
             valid = True
             try:
-                self.common.validate_downloads_dir()
-            except DownloadsDirErrorCannotCreate:
-                self.web.add_request(self.web.REQUEST_ERROR_DOWNLOADS_DIR_CANNOT_CREATE, request.path)
-                print(strings._('error_cannot_create_downloads_dir').format(self.common.settings.get('downloads_dir')))
-                valid = False
-            except DownloadsDirErrorNotWritable:
-                self.web.add_request(self.web.REQUEST_ERROR_DOWNLOADS_DIR_NOT_WRITABLE, request.path)
-                print(strings._('error_downloads_dir_not_writable').format(self.common.settings.get('downloads_dir')))
+                os.makedirs(receive_mode_dir, 0o700)
+            except PermissionError:
+                self.web.add_request(self.web.REQUEST_ERROR_DOWNLOADS_DIR_CANNOT_CREATE, request.path, {
+                    "receive_mode_dir": receive_mode_dir
+                })
+                print(strings._('error_cannot_create_downloads_dir').format(receive_mode_dir))
                 valid = False
             if not valid:
                 flash('Error uploading, please inform the OnionShare user', 'error')
@@ -86,7 +87,7 @@ class ReceiveModeWeb(object):
                     # Automatically rename the file, if a file of the same name already exists
                     filename = secure_filename(f.filename)
                     filenames.append(filename)
-                    local_path = os.path.join(self.common.settings.get('downloads_dir'), filename)
+                    local_path = os.path.join(receive_mode_dir, filename)
                     if os.path.exists(local_path):
                         if '.' in filename:
                             # Add "-i", e.g. change "foo.txt" to "foo-2.txt"
@@ -98,7 +99,7 @@ class ReceiveModeWeb(object):
                             valid = False
                             while not valid:
                                 new_filename = '{}-{}.{}'.format('.'.join(name), i, ext)
-                                local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename)
+                                local_path = os.path.join(receive_mode_dir, new_filename)
                                 if os.path.exists(local_path):
                                     i += 1
                                 else:
@@ -109,7 +110,7 @@ class ReceiveModeWeb(object):
                             valid = False
                             while not valid:
                                 new_filename = '{}-{}'.format(filename, i)
-                                local_path = os.path.join(self.common.settings.get('downloads_dir'), new_filename)
+                                local_path = os.path.join(receive_mode_dir, new_filename)
                                 if os.path.exists(local_path):
                                     i += 1
                                 else:
diff --git a/onionshare/web/web.py b/onionshare/web/web.py
index 52c4da16..2ae011b7 100644
--- a/onionshare/web/web.py
+++ b/onionshare/web/web.py
@@ -39,7 +39,6 @@ class Web(object):
     REQUEST_UPLOAD_FILE_RENAMED = 7
     REQUEST_UPLOAD_FINISHED = 8
     REQUEST_ERROR_DOWNLOADS_DIR_CANNOT_CREATE = 9
-    REQUEST_ERROR_DOWNLOADS_DIR_NOT_WRITABLE = 10
 
     def __init__(self, common, is_gui, mode='share'):
         self.common = common
diff --git a/onionshare_gui/onionshare_gui.py b/onionshare_gui/onionshare_gui.py
index 8c8e4e73..1e254f61 100644
--- a/onionshare_gui/onionshare_gui.py
+++ b/onionshare_gui/onionshare_gui.py
@@ -394,10 +394,7 @@ class OnionShareGui(QtWidgets.QMainWindow):
                 mode.handle_request_upload_finished(event)
 
             if event["type"] == Web.REQUEST_ERROR_DOWNLOADS_DIR_CANNOT_CREATE:
-                Alert(self.common, strings._('error_cannot_create_downloads_dir').format(self.common.settings.get('downloads_dir')))
-
-            if event["type"] == Web.REQUEST_ERROR_DOWNLOADS_DIR_NOT_WRITABLE:
-                Alert(self.common, strings._('error_downloads_dir_not_writable').format(self.common.settings.get('downloads_dir')))
+                Alert(self.common, strings._('error_cannot_create_downloads_dir').format(event["data"]["receive_mode_dir"]))
 
             if event["type"] == Web.REQUEST_OTHER:
                 if event["path"] != '/favicon.ico' and event["path"] != "/{}/shutdown".format(mode.web.shutdown_slug):
diff --git a/share/locale/en.json b/share/locale/en.json
index db416c9b..d57ef3f3 100644
--- a/share/locale/en.json
+++ b/share/locale/en.json
@@ -155,7 +155,6 @@
     "info_in_progress_uploads_tooltip": "{} upload(s) in progress",
     "info_completed_uploads_tooltip": "{} upload(s) completed",
     "error_cannot_create_downloads_dir": "Could not create receive mode folder: {}",
-    "error_downloads_dir_not_writable": "The receive mode folder is write protected: {}",
     "receive_mode_downloads_dir": "Files sent to you appear in this folder: {}",
     "receive_mode_warning": "Warning: Receive mode lets people upload files to your computer. Some files can potentially take control of your computer if you open them. Only open things from people you trust, or if you know what you are doing.",
     "gui_receive_mode_warning": "Receive mode lets people upload files to your computer.<br><br><b>Some files can potentially take control of your computer if you open them. Only open things from people you trust, or if you know what you are doing.</b>",