massive change on how files are accessed.

moved from prviding a path to using unique id's
if there might have been any directory traversal issues they should be gone now.
This commit is contained in:
ajurna@gmail.com
2016-04-01 09:56:42 +01:00
parent d2f880bbae
commit 1a37db8f22
13 changed files with 555 additions and 145 deletions

View File

@@ -1,5 +1,5 @@
from django.contrib import admin from django.contrib import admin
from comic.models import Setting, ComicBook, ComicPage, ComicStatus from comic.models import Setting, ComicBook, ComicPage, ComicStatus, Directory
@admin.register(Setting) @admin.register(Setting)
@@ -17,6 +17,12 @@ class ComicPageAdmin(admin.ModelAdmin):
list_display = ('Comic', 'index', 'page_file_name', 'content_type') list_display = ('Comic', 'index', 'page_file_name', 'content_type')
list_filter = ['Comic'] list_filter = ['Comic']
@admin.register(ComicStatus) @admin.register(ComicStatus)
class ComicStatusAdmin(admin.ModelAdmin): class ComicStatusAdmin(admin.ModelAdmin):
list_display = ['user', 'comic', 'last_read_page', 'unread'] list_display = ['user', 'comic', 'last_read_page', 'unread']
@admin.register(Directory)
class DirectoryAdmin(admin.ModelAdmin):
pass

View File

View File

View File

@@ -0,0 +1,52 @@
from django.core.management.base import BaseCommand
from comic.models import Setting, Directory, ComicBook
import os
from os.path import isdir
class Command(BaseCommand):
help = 'Scan directories to Update Comic DB'
def __init__(self):
super().__init__()
self.base_dir = Setting.objects.get(name='BASE_DIR').value
def handle(self, *args, **options):
self.scan_directory()
def scan_directory(self, directory=False):
"""
:type directory: Directory
"""
if not directory:
comic_dir = self.base_dir
else:
comic_dir = os.path.join(self.base_dir, directory.get_path())
for file in os.listdir(comic_dir):
if isdir(os.path.join(comic_dir, file)):
if directory:
next_directory, created = Directory.objects.get_or_create(name=file,
parent=directory)
else:
next_directory, created = Directory.objects.get_or_create(name=file,
parent__isnull=True)
if created:
next_directory.save()
self.scan_directory(next_directory)
else:
try:
if directory:
ComicBook.objects.get(file_name=file,
directory=directory)
else:
ComicBook.objects.get(file_name=file,
directory__isnull=True)
except ComicBook.DoesNotExist:
ComicBook.process_comic_book(file, directory)

View File

@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-03-31 10:40
from __future__ import unicode_literals
import datetime
from django.db import migrations, models
import django.db.models.deletion
from django.utils.timezone import utc
import uuid
class Migration(migrations.Migration):
dependencies = [
('comic', '0007_auto_20150626_1820'),
]
operations = [
migrations.CreateModel(
name='Directory',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('selector', models.UUIDField(default=uuid.uuid4, null=True)),
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='comic.Directory')),
],
),
migrations.AddField(
model_name='comicbook',
name='date_added',
field=models.DateTimeField(auto_now_add=True, default=datetime.datetime(2016, 3, 31, 10, 40, 30, 62170, tzinfo=utc)),
preserve_default=False,
),
migrations.AddField(
model_name='comicbook',
name='selector',
field=models.UUIDField(default=uuid.uuid4, null=True),
),
migrations.AddField(
model_name='comicbook',
name='version',
field=models.IntegerField(default=0),
),
migrations.AddField(
model_name='comicbook',
name='directory',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='comic.Directory'),
),
]

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-03-31 10:40
from __future__ import unicode_literals
from django.db import migrations
import uuid
def gen_uuid(apps, schema_editor):
comicbook = apps.get_model('comic', 'comicbook')
for row in comicbook.objects.all():
row.selector = uuid.uuid4()
row.save()
directory = apps.get_model('comic', 'directory')
for row in directory.objects.all():
row.selector = uuid.uuid4()
row.save()
class Migration(migrations.Migration):
dependencies = [
('comic', '0008_auto_20160331_1140'),
]
operations = [
migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop),
]

View File

@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-03-31 10:40
from __future__ import unicode_literals
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('comic', '0009_auto_20160331_1140'),
]
operations = [
migrations.AlterField(
model_name='comicbook',
name='selector',
field=models.UUIDField(default=uuid.uuid4, unique=True),
),
migrations.AlterField(
model_name='directory',
name='selector',
field=models.UUIDField(default=uuid.uuid4, unique=True),
),
]

View File

@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-03-31 10:41
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('comic', '0010_auto_20160331_1140'),
]
operations = [
migrations.AlterField(
model_name='comicbook',
name='version',
field=models.IntegerField(default=1),
),
]

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-04-01 08:49
from __future__ import unicode_literals
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('comic', '0011_auto_20160331_1141'),
]
operations = [
migrations.AlterField(
model_name='comicbook',
name='selector',
field=models.UUIDField(db_index=True, default=uuid.uuid4, unique=True),
),
migrations.AlterField(
model_name='directory',
name='selector',
field=models.UUIDField(db_index=True, default=uuid.uuid4, unique=True),
),
]

View File

@@ -1,13 +1,14 @@
from django.db import models from django.db import models
from django.db.transaction import atomic
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.conf import settings from django.conf import settings
from django.db.transaction import atomic
from comic import rarfile from comic import rarfile
from comic.util import get_ordered_dir_list
import uuid
import zipfile import zipfile
from os import path from os import path, listdir
if settings.UNRAR_TOOL: if settings.UNRAR_TOOL:
rarfile.UNRAR_TOOL = settings.UNRAR_TOOL rarfile.UNRAR_TOOL = settings.UNRAR_TOOL
@@ -24,13 +25,67 @@ class Setting(models.Model):
return self.__str__() return self.__str__()
class Directory(models.Model):
name = models.CharField(max_length=100)
parent = models.ForeignKey('Directory', null=True, blank=True)
selector = models.UUIDField(unique=True, default=uuid.uuid4, db_index=True)
def __str__(self):
return 'Directory: {0}; {1}'.format(self.name, self.parent)
@property
def path(self):
l = self.get_path_items()
l.reverse()
return path.sep.join(l)
def get_path(self):
l = self.get_path_items()
l.reverse()
return path.sep.join(l)
def get_path_items(self, p=False):
if not p:
p = []
p.append(self.name)
if self.parent:
self.parent.get_path_items(p)
return p
def get_path_objects(self, p=False):
if not p:
p = []
p.append(self)
if self.parent:
self.parent.get_path_objects(p)
return p
@staticmethod
def get_dir_from_path(file_path):
file_path = file_path.split(path.sep)
print(file_path)
for d in Directory.objects.filter(name=file_path[-1]):
print(d)
if d.get_path_items() == file_path:
return d
class ComicBook(models.Model): class ComicBook(models.Model):
file_name = models.CharField(max_length=100, unique=True) file_name = models.CharField(max_length=100, unique=True)
date_added = models.DateTimeField(auto_now_add=True)
directory = models.ForeignKey(Directory, blank=True, null=True)
selector = models.UUIDField(unique=True, default=uuid.uuid4, db_index=True)
version = models.IntegerField(default=1)
def __str__(self): def __str__(self):
return self.file_name return self.file_name
def get_image(self, archive_path, page): def get_image(self, page):
base_dir = Setting.objects.get(name='BASE_DIR').value
if self.directory:
archive_path = path.join(base_dir, self.directory.path, self.file_name)
else:
archive_path = path.join(base_dir, self.file_name)
try: try:
archive = rarfile.RarFile(archive_path) archive = rarfile.RarFile(archive_path)
except rarfile.NotRarFile: except rarfile.NotRarFile:
@@ -62,120 +117,103 @@ class ComicBook(models.Model):
self.q_prev_to_directory = False self.q_prev_to_directory = False
self.q_next_to_directory = False self.q_next_to_directory = False
def nav(self, comic_path, page): def nav(self, page, user):
out = self.Navigation() out = self.Navigation()
out.cur_index = page out.cur_index = page
out.cur_path = comic_path out.cur_path = urlsafe_base64_encode(self.selector.bytes)
if page == 0: if page == 0:
out.prev_path, out.prev_index = self.nav_get_prev_comic(comic_path) out.prev_path, out.prev_index = self.nav_get_prev_comic(user)
if out.prev_index == -1: if out.prev_index == -1:
out.q_prev_to_directory = True out.q_prev_to_directory = True
else: else:
out.prev_index = page - 1 out.prev_index = page - 1
out.prev_path = comic_path out.prev_path = out.cur_path
if self.is_last_page(page): if self.is_last_page(page):
out.next_path, out.next_index = self.nav_get_next_comic(comic_path) out.next_path, out.next_index = self.nav_get_next_comic(user)
if out.next_index == -1: if out.next_index == -1:
out.q_next_to_directory = True out.q_next_to_directory = True
else: else:
out.next_index = page + 1 out.next_index = page + 1
out.next_path = comic_path out.next_path = out.cur_path
return out return out
@staticmethod def nav_get_prev_comic(self, user):
def nav_get_prev_comic(comic_path):
base_dir = Setting.objects.get(name='BASE_DIR').value base_dir = Setting.objects.get(name='BASE_DIR').value
comic_path = urlsafe_base64_decode(comic_path).decode() if self.directory:
directory, comic = path.split(comic_path) folder = path.join(base_dir, self.directory.path)
dir_list = get_ordered_dir_list(path.join(base_dir, directory)) else:
comic_index = dir_list.index(comic) folder = base_dir
dir_list = ComicBook.get_ordered_dir_list(folder)
comic_index = dir_list.index(self.file_name)
if comic_index == 0: if comic_index == 0:
comic_path = urlsafe_base64_encode(directory.encode()) if self.directory:
comic_path = urlsafe_base64_encode(self.directory.selector.bytes)
else:
comic_path = ''
index = -1 index = -1
else: else:
prev_comic = dir_list[comic_index - 1] prev_comic = dir_list[comic_index - 1]
comic_path = path.join(directory, prev_comic)
if not path.isdir(path.join(base_dir, directory, prev_comic)): if not path.isdir(path.join(folder, prev_comic)):
try: try:
book = ComicBook.objects.get(file_name=prev_comic) if self.directory:
except ComicBook.DoesNotExist: book = ComicBook.objects.get(file_name=prev_comic,
book = ComicBook.process_comic_book(base_dir, comic_path, prev_comic) directory=self.directory)
index = ComicPage.objects.filter(Comic=book).count() - 1
comic_path = urlsafe_base64_encode(comic_path.encode())
else: else:
comic_path = urlsafe_base64_encode(directory.encode()) book = ComicBook.objects.get(file_name=prev_comic,
directory__isnull=True)
except ComicBook.DoesNotExist:
if self.directory:
book = ComicBook.process_comic_book(prev_comic, self.directory)
else:
book = ComicBook.process_comic_book(prev_comic)
cs, _ = ComicStatus.objects.get_or_create(comic=book, user=user)
index = cs.last_read_page
comic_path = urlsafe_base64_encode(book.selector.bytes)
else:
if self.directory:
comic_path = urlsafe_base64_encode(self.directory.selector.bytes)
else:
comic_path = ''
index = -1 index = -1
return comic_path, index return comic_path, index
@staticmethod def nav_get_next_comic(self, user):
def nav_get_next_comic(comic_path): base_dir = Setting.objects.get(name='BASE_DIR').value
base_dir = Setting.objects.get(name='BASE_DIR') if self.directory:
comic_path = urlsafe_base64_decode(comic_path).decode() folder = path.join(base_dir, self.directory.path)
directory, comic = path.split(comic_path) else:
dir_list = get_ordered_dir_list(path.join(base_dir.value, directory)) folder = base_dir
comic_index = dir_list.index(comic) dir_list = ComicBook.get_ordered_dir_list(folder)
comic_index = dir_list.index(self.file_name)
try: try:
next_comic = dir_list[comic_index + 1] next_comic = dir_list[comic_index + 1]
comic_path = path.join(directory, next_comic) try:
comic_path = urlsafe_base64_encode(comic_path) if self.directory:
index = 0 book = ComicBook.objects.get(file_name=next_comic,
directory=self.directory)
else:
book = ComicBook.objects.get(file_name=next_comic,
directory__isnull=True)
except ComicBook.DoesNotExist:
if self.directory:
book = ComicBook.process_comic_book(next_comic, self.directory)
else:
book = ComicBook.process_comic_book(next_comic)
comic_path = urlsafe_base64_encode(book.selector.bytes)
cs, _ = ComicStatus.objects.get_or_create(comic=book, user=user)
index = cs.last_read_page
except IndexError: except IndexError:
comic_path = urlsafe_base64_encode(directory) if self.directory:
comic_path = urlsafe_base64_encode(self.directory.selector.bytes)
else:
comic_path = ''
index = -1 index = -1
return comic_path, index return comic_path, index
@staticmethod
def process_comic_book(base_dir, comic_path, comic_file_name):
try:
cbx = rarfile.RarFile(path.join(base_dir, comic_path))
except rarfile.NotRarFile:
cbx = zipfile.ZipFile(path.join(base_dir, comic_path))
except zipfile.BadZipfile:
return False
with atomic():
book = ComicBook(file_name=comic_file_name)
book.save()
i = 0
for f in sorted([str(x) for x in cbx.namelist()], key=str.lower):
try:
dot_index = f.rindex('.') + 1
except ValueError:
continue
ext = f.lower()[dot_index:]
if ext in ['jpg', 'jpeg']:
page = ComicPage(Comic=book,
index=i,
page_file_name=f,
content_type='image/jpeg')
page.save()
i += 1
elif ext == 'png':
page = ComicPage(Comic=book,
index=i,
page_file_name=f,
content_type='image/png')
page.save()
i += 1
elif ext == 'bmp':
page = ComicPage(Comic=book,
index=i,
page_file_name=f,
content_type='image/bmp')
page.save()
i += 1
elif ext == 'gif':
page = ComicPage(Comic=book,
index=i,
page_file_name=f,
content_type='image/gif')
page.save()
i += 1
return book
class DirFile: class DirFile:
def __init__(self): def __init__(self):
self.name = '' self.name = ''
@@ -192,7 +230,7 @@ class ComicBook(models.Model):
@staticmethod @staticmethod
def generate_directory(user, base_dir, comic_path): def generate_directory(user, base_dir, comic_path):
files = [] files = []
for fn in get_ordered_dir_list(path.join(base_dir, comic_path)): for fn in ComicBook.get_ordered_dir_list(path.join(base_dir, comic_path)):
df = ComicBook.DirFile() df = ComicBook.DirFile()
df.name = fn df.name = fn
if path.isdir(path.join(base_dir, comic_path, fn)): if path.isdir(path.join(base_dir, comic_path, fn)):
@@ -232,6 +270,76 @@ class ComicBook(models.Model):
def page_name(self, index): def page_name(self, index):
return ComicPage.objects.get(Comic=self, index=index).page_file_name return ComicPage.objects.get(Comic=self, index=index).page_file_name
@staticmethod
def process_comic_book(comic_file_name, directory=False):
"""
:type comic_file_name: str
:type directory: Directory
"""
try:
book = ComicBook.objects.get(file_name=comic_file_name,
version=0)
book.directory = directory
book.version = 1
book.save()
return book
except ComicBook.DoesNotExist:
pass
base_dir = Setting.objects.get(name='BASE_DIR').value
if directory:
comic_full_path = path.join(base_dir, directory.get_path(), comic_file_name)
else:
comic_full_path = path.join(base_dir, comic_file_name)
try:
cbx = rarfile.RarFile(comic_full_path)
except rarfile.NotRarFile:
cbx = zipfile.ZipFile(comic_full_path)
except zipfile.BadZipfile:
return False
with atomic():
if directory:
book = ComicBook(file_name=comic_file_name,
directory=directory)
else:
book = ComicBook(file_name=comic_file_name)
book.save()
page_index = 0
for page_file_name in sorted([str(x) for x in cbx.namelist()], key=str.lower):
try:
dot_index = page_file_name.rindex('.') + 1
except ValueError:
continue
ext = page_file_name.lower()[dot_index:]
if ext in ['jpg', 'jpeg']:
content_type = 'image/jpeg'
elif ext == 'png':
content_type = 'image/png'
elif ext == 'bmp':
content_type = 'image/bmp'
elif ext == 'gif':
content_type = 'image/gif'
else:
content_type = 'text/plain'
page = ComicPage(Comic=book,
index=page_index,
page_file_name=page_file_name,
content_type=content_type)
page.save()
page_index += 1
return book
@staticmethod
def get_ordered_dir_list(folder):
directories = []
files = []
for item in listdir(folder):
if path.isdir(path.join(folder, item)):
directories.append(item)
else:
files.append(item)
return sorted(directories) + sorted(files)
class ComicPage(models.Model): class ComicPage(models.Model):
Comic = models.ForeignKey(ComicBook) Comic = models.ForeignKey(ComicBook)
@@ -246,5 +354,4 @@ class ComicStatus(models.Model):
last_read_page = models.IntegerField(default=0) last_read_page = models.IntegerField(default=0)
unread = models.BooleanField(default=True) unread = models.BooleanField(default=True)
# TODO: add support to reference items last being read # TODO: add support to reference items last being read

View File

@@ -9,7 +9,7 @@ urlpatterns = [
url(r'^settings/users/(?P<user_id>[0-9]+)/$', views.user_config_page, name='users'), url(r'^settings/users/(?P<user_id>[0-9]+)/$', views.user_config_page, name='users'),
url(r'^settings/users/add/$', views.user_add_page, name='users'), url(r'^settings/users/add/$', views.user_add_page, name='users'),
url(r'^account/$', views.account_page, name='account'), url(r'^account/$', views.account_page, name='account'),
url(r'^(?P<comic_path>[\w]+)/$', views.comic_list, name='comic_list'), url(r'^read/(?P<comic_selector>[\w-]+)/(?P<page>[0-9]+)/$', views.read_comic, name='read_comic'),
url(r'^read/(?P<comic_path>[\w]+)/(?P<page>[0-9]+)/$', views.read_comic, name='read_comic'), url(r'^read/(?P<comic_selector>[\w-]+)/(?P<page>[0-9]+)/img$', views.get_image, name='get_image'),
url(r'^read/(?P<comic_path>[\w]+)/(?P<page>[0-9]+)/img$', views.get_image, name='get_image'), url(r'^(?P<directory_selector>[\w-]+)/$', views.comic_list, name='comic_list'),
] ]

View File

@@ -1,14 +1,15 @@
from collections import OrderedDict
from os import path, listdir
from django.utils.http import urlsafe_base64_encode from django.utils.http import urlsafe_base64_encode
from os import path from .models import ComicBook, Setting, ComicStatus, Directory
from collections import OrderedDict
import os
def generate_title_from_path(path): def generate_title_from_path(file_path):
if path == '': if file_path == '':
return 'CBWebReader' return 'CBWebReader'
return 'CBWebReader - ' + ' - '.join(path.split(os.sep)) return 'CBWebReader - ' + ' - '.join(file_path.split(path.sep))
class Menu: class Menu:
@@ -39,19 +40,22 @@ class Breadcrumb:
return self.name return self.name
def generate_breadcrumbs_from_path(comic_path): def generate_breadcrumbs_from_path(directory=False):
"""
:type directory: Directory
"""
output = [Breadcrumb()] output = [Breadcrumb()]
prefix = '/comic/' prefix = b'/comic/'
last = '' last = ''
comic_path = path.normpath(comic_path) if directory:
folders = comic_path.split(os.sep) folders = directory.get_path_objects()
for item in folders: else:
if item == '.': folders = []
continue for item in folders[::-1]:
bc = Breadcrumb() bc = Breadcrumb()
bc.name = item bc.name = item.name
last = path.join(last, item) bc.url = prefix + urlsafe_base64_encode(item.selector.bytes)
bc.url = prefix + urlsafe_base64_encode(last.encode()).decode()
output.append(bc) output.append(bc)
return output return output
@@ -66,12 +70,93 @@ def generate_breadcrumbs_from_menu(paths):
return output return output
def generate_directory(user, directory=False):
"""
:type user: User
:type directory: Directory
"""
base_dir = Setting.objects.get(name='BASE_DIR').value
files = []
if directory:
dir_path = directory.path
ordered_dir_list = get_ordered_dir_list(path.join(base_dir, directory.path))
else:
dir_path = ''
ordered_dir_list = get_ordered_dir_list(base_dir)
for file_name in ordered_dir_list:
df = ComicBook.DirFile()
df.name = file_name
if path.isdir(path.join(base_dir, dir_path, file_name)):
if directory:
d = Directory.objects.get(name=file_name,
parent=directory)
else:
d = Directory.objects.get(name=file_name,
parent__isnull=True)
df.isdir = True
df.icon = 'glyphicon-folder-open'
df.location = urlsafe_base64_encode(d.selector.bytes)
elif file_name.lower()[-4:] in ['.rar', '.zip', '.cbr', '.cbz']:
df.iscb = True
df.icon = 'glyphicon-book'
try:
if directory:
book = ComicBook.objects.get(file_name=file_name,
directory=directory)
else:
book = ComicBook.objects.get(file_name=file_name,
directory__isnull=True)
except ComicBook.DoesNotExist:
book = ComicBook.process_comic_book(file_name, directory)
df.location = urlsafe_base64_encode(book.selector.bytes)
status, _ = ComicStatus.objects.get_or_create(comic=book, user=user)
last_page = status.last_read_page
if status.unread:
df.label = '<span class="label label-default pull-right">Unread</span>'
elif (last_page + 1) == book.page_count:
df.label = '<span class="label label-success pull-right">Read</span>'
df.cur_page = last_page
else:
label_text = '<span class="label label-primary pull-right">%s/%s</span>' % \
(last_page + 1, book.page_count)
df.label = label_text
df.cur_page = last_page
# df.label = '<span class="label label-danger pull-right">Unprocessed</span>'
files.append(df)
return files
def get_ordered_dir_list(folder): def get_ordered_dir_list(folder):
directories = [] directories = []
files = [] files = []
for item in os.listdir(folder): for item in listdir(folder):
if path.isdir(path.join(folder, item)): if path.isdir(path.join(folder, item)):
directories.append(item) directories.append(item)
else: else:
files.append(item) files.append(item)
return sorted(directories) + sorted(files) return sorted(directories) + sorted(files)
def scan_directory(directory=False):
"""
TODO: Increase efficiency of this. reduce amount of queries.
:type directory: Directory
"""
base_dir = Setting.objects.get(name='BASE_DIR').value
# filter(os.path.isdir, os.listdir(os.getcwd()))
if directory:
full_path = path.join(base_dir, directory.path)
else:
full_path = base_dir
dir_list = listdir(full_path)
directorys = [d for d in dir_list if path.isdir(path.join(full_path, d))]
for direct in directorys:
if directory:
d, created = Directory.objects.get_or_create(name=direct,
parent=directory)
else:
d, created = Directory.objects.get_or_create(name=direct)
if created:
d.save()

View File

@@ -1,20 +1,21 @@
from django.http import HttpResponse import uuid
from django.template import RequestContext from os import path
from django.utils.http import urlsafe_base64_decode
from django.shortcuts import render, redirect, get_object_or_404 from django.contrib.auth import login, authenticate
from django.contrib.auth.decorators import login_required, user_passes_test from django.contrib.auth.decorators import login_required, user_passes_test
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth import login, authenticate from django.http import HttpResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.utils.http import urlsafe_base64_decode
from .models import Setting, ComicBook, ComicStatus
from .util import generate_breadcrumbs_from_path, generate_breadcrumbs_from_menu, generate_title_from_path, Menu
from .forms import SettingsForm, AccountForm, EditUserForm, AddUserForm, InitialSetupForm from .forms import SettingsForm, AccountForm, EditUserForm, AddUserForm, InitialSetupForm
from .models import Setting, ComicBook, ComicStatus, Directory
from os import path from .util import generate_breadcrumbs_from_path, generate_breadcrumbs_from_menu, \
generate_title_from_path, Menu, generate_directory, scan_directory
@login_required @login_required
def comic_list(request, comic_path=''): def comic_list(request, directory_selector=False):
try: try:
base_dir = Setting.objects.get(name='BASE_DIR').value base_dir = Setting.objects.get(name='BASE_DIR').value
except Setting.DoesNotExist: except Setting.DoesNotExist:
@@ -22,16 +23,28 @@ def comic_list(request, comic_path=''):
if not path.isdir(base_dir): if not path.isdir(base_dir):
return redirect('/comic/settings/') return redirect('/comic/settings/')
comic_path = urlsafe_base64_decode(comic_path).decode() if directory_selector:
title = generate_title_from_path(comic_path) directory_selector = uuid.UUID(bytes=urlsafe_base64_decode(directory_selector))
files = ComicBook.generate_directory(request.user, base_dir, comic_path) directory = Directory.objects.get(selector=directory_selector)
context = { else:
directory = False
scan_directory(directory)
if directory:
title = generate_title_from_path(directory.path)
breadcrumbs = generate_breadcrumbs_from_path(directory)
else:
title = generate_title_from_path('Home')
breadcrumbs = generate_breadcrumbs_from_path()
files = generate_directory(request.user, directory)
return render(request, 'comic/comic_list.html', {
'file_list': files, 'file_list': files,
'breadcrumbs': generate_breadcrumbs_from_path(comic_path), 'breadcrumbs': breadcrumbs,
'menu': Menu(request.user, 'Browse'), 'menu': Menu(request.user, 'Browse'),
'title': title, 'title': title,
} })
return render(request, 'comic/comic_list.html', context)
@login_required @login_required
@@ -184,16 +197,19 @@ def settings_page(request):
@login_required @login_required
def read_comic(request, comic_path, page): def read_comic(request, comic_selector, page):
base_dir = Setting.objects.get(name='BASE_DIR').value base_dir = Setting.objects.get(name='BASE_DIR').value
page = int(page) page = int(page)
decoded_path = urlsafe_base64_decode(comic_path).decode() selector = uuid.UUID(bytes=urlsafe_base64_decode(comic_selector))
breadcrumbs = generate_breadcrumbs_from_path(decoded_path) book = get_object_or_404(ComicBook, selector=selector)
_, comic_file_name = path.split(decoded_path)
try: breadcrumbs = generate_breadcrumbs_from_path(book.directory)
book = ComicBook.objects.get(file_name=comic_file_name) #comic_file_path, comic_file_name = path.split(decoded_path)
except ComicBook.DoesNotExist: #d = Directory.get_dir_from_path(comic_file_path)
book = ComicBook.process_comic_book(base_dir, decoded_path, comic_file_name) #try:
# book = ComicBook.objects.get(file_name=comic_file_name)
#except ComicBook.DoesNotExist:
# book = ComicBook.process_comic_book(comic_file_name, d)
status, _ = ComicStatus.objects.get_or_create(comic=book, user=request.user) status, _ = ComicStatus.objects.get_or_create(comic=book, user=request.user)
status.unread = False status.unread = False
status.last_read_page = page status.last_read_page = page
@@ -202,7 +218,7 @@ def read_comic(request, comic_path, page):
context = { context = {
'book': book, 'book': book,
'orig_file_name': book.page_name(page), 'orig_file_name': book.page_name(page),
'nav': book.nav(comic_path, page), 'nav': book.nav(page, request.user),
'breadcrumbs': breadcrumbs, 'breadcrumbs': breadcrumbs,
'menu': Menu(request.user), 'menu': Menu(request.user),
'title': title, 'title': title,
@@ -211,17 +227,10 @@ def read_comic(request, comic_path, page):
@login_required @login_required
def get_image(_, comic_path, page): def get_image(_, comic_selector, page):
base_dir = Setting.objects.get(name='BASE_DIR').value selector = uuid.UUID(bytes=urlsafe_base64_decode(comic_selector))
page = int(page) book = ComicBook.objects.get(selector=selector)
decoded_path = urlsafe_base64_decode(comic_path).decode() img, content = book.get_image(int(page))
_, comic_file_name = path.split(decoded_path)
try:
book = ComicBook.objects.get(file_name=comic_file_name)
except ComicBook.DoesNotExist:
book = ComicBook.process_comic_book(base_dir, decoded_path, comic_file_name)
full_path = path.join(base_dir, decoded_path)
img, content = book.get_image(full_path, page)
return HttpResponse(img.read(), content_type=content) return HttpResponse(img.read(), content_type=content)