diff --git a/zerobin/paste.py b/zerobin/paste.py index bb5c456..8211bf8 100644 --- a/zerobin/paste.py +++ b/zerobin/paste.py @@ -264,3 +264,64 @@ class Paste(object): Delete the paste file. """ os.remove(self.path) + + def is_alive(self): + """ + Return True if the paste is alive. + False if it may be deleted + """ + now = datetime.now() + # keep alive false by default + keep_alive = False + # Delete the paste if it expired: + if 'burn_after_reading' in str(self.expiration): + # burn_after_reading contains the paste creation date + # if this read appends 10 seconds after the creation date + # we don't delete the paste because it means it's the redirection + # to the paste that happens during the paste creation + try: + keep_alive = self.expiration.split('#')[1] + keep_alive = datetime.strptime(keep_alive, + '%Y-%m-%d %H:%M:%S.%f') + keep_alive = now < keep_alive + timedelta(seconds=10) + except IndexError: + keep_alive = False + else: + keep_alive = now < self.expiration + + return keep_alive + + + @classmethod + def purge(self, path=settings.PASTE_FILES_ROOT): + """ + Purge the content folder + Return the number of paste deleted. + """ + # we don't want to read 'counter' files + ignore_files = ['counter', ] + # keep a count on purged pastes + deleted_paste = 0 + if os.path.exists(path): + for folder, _ , files in os.walk(path): + for fname in files: + if fname in ignore_files: + continue + if Paste._purge_file(os.path.join(folder, fname)): + deleted_paste += 1 + return deleted_paste + + @classmethod + def _purge_file(self, fname): + """ + Purges the given file if expired. + """ + paste = Paste.load_from_file(fname) + # Burn after reading will always returns paste.is_alive() == False + # We don't want to kill them now + is_burn_after_reading = 'burn_after_reading' in str(paste.expiration) + if not is_burn_after_reading and not paste.is_alive(): + paste.delete() + return True + return False + diff --git a/zerobin/routes.py b/zerobin/routes.py index ab8ffaa..7274a69 100644 --- a/zerobin/routes.py +++ b/zerobin/routes.py @@ -104,23 +104,7 @@ def display_paste(paste_id): keep_alive = False try: paste = Paste.load(paste_id) - # Delete the paste if it expired: - if 'burn_after_reading' in str(paste.expiration): - # burn_after_reading contains the paste creation date - # if this read appends 10 seconds after the creation date - # we don't delete the paste because it means it's the redirection - # to the paste that happens during the paste creation - try: - keep_alive = paste.expiration.split('#')[1] - keep_alive = datetime.strptime(keep_alive, - '%Y-%m-%d %H:%M:%S.%f') - keep_alive = now < keep_alive + timedelta(seconds=10) - except IndexError: - keep_alive = False - if not keep_alive: - paste.delete() - - elif paste.expiration < now: + if not paste.is_alive(): paste.delete() raise ValueError() @@ -176,18 +160,25 @@ def get_app(debug=None, settings_file='', @clize.clize(coerce={'debug': bool, 'compressed_static': bool}) def runserver(host='', port='', debug=None, user='', group='', settings_file='', compressed_static=None, - version=False, paste_id_length=None, server="cherrypy"): + version=False, paste_id_length=None, server="cherrypy", purge=False): if version: print '0bin V%s' % settings.VERSION sys.exit(0) + if purge: + print 'Purging expired pastes excluding burn notices' + purged_pastes = Paste.purge() + print 'Done (%s pastes removed)' % (purged_pastes) + sys.exit(0) + settings.HOST = host or settings.HOST settings.PORT = port or settings.PORT settings.USER = user or settings.USER settings.GROUP = group or settings.GROUP settings.PASTE_ID_LENGTH = paste_id_length or settings.PASTE_ID_LENGTH + try: _, app = get_app(debug, settings_file, compressed_static, settings=settings) except SettingsValidationError as err: