Exemple #1
0
def upload_file(request):

    selected_theme = request.GET.get("theme_edit", get_theme())
    if not is_valid_theme(selected_theme):
        raise Http404(_('Specified theme does not exist'))
    if is_theme_read_only(selected_theme):
        raise Http403

    if request.method == 'POST':
        form = UploadForm(request.POST, request.FILES)

        if form.is_valid():
            file_dir = form.cleaned_data['file_dir']
            overwrite = form.cleaned_data['overwrite']

            def callback(file_path, uuid, selected_theme=selected_theme, file_dir=file_dir, overwrite=overwrite):
                theme_root = get_theme_root(selected_theme)
                file_name = os.path.basename(file_path)
                full_filename = os.path.join(file_dir, file_name)
                if (not is_valid_path(theme_root, file_dir) or
                    not is_valid_path(theme_root, full_filename)):
                    raise Http403
                if os.path.isfile(os.path.join(theme_root, full_filename)) and not overwrite:
                    msg_string = 'File %s already exists in that folder.' % (file_name)
                    raise uploader.CallbackError(msg_string)
                copy_file_to_theme(file_path, selected_theme, file_dir, file_name)
                EventLog.objects.log()
            return uploader.post(request, callback)

        else:  # not valid
            messages.add_message(request, messages.ERROR, form.errors)
            return HttpResponse('invalid', content_type="text/plain")

    return HttpResponseRedirect('/theme-editor/editor/')
Exemple #2
0
def theme_rename(request, form_class=ThemeNameForm):
    if not request.user.profile.is_superuser:
        raise Http403

    selected_theme = request.GET.get("theme_edit", get_theme())
    if not is_valid_theme(selected_theme):
        raise Http404(_('Specified theme does not exist'))
    if is_theme_read_only(selected_theme):
        raise Http403
    theme_root = get_theme_root(selected_theme)

    form = form_class(request.POST or None)
    ret_dict = {'success': False, 'err': ''}

    if form.is_valid():
        new_theme_name = form.cleaned_data['theme_name']
        if is_valid_theme(new_theme_name):
            ret_dict['err'] = _('Theme "%(name)s" already exists' %
                                {'name': new_theme_name})
            return HttpResponse(json.dumps(ret_dict))
        if not is_valid_path(settings.ORIGINAL_THEMES_DIR, new_theme_name):
            raise Http403
        new_theme_root = get_theme_root(new_theme_name)
        shutil.move(theme_root, new_theme_root)
        ret_dict['success'] = True
        EventLog.objects.log()
    #else:
    #    ret_dict['err'] = form.errors.as_json()

    return HttpResponse(json.dumps(ret_dict))
Exemple #3
0
def original_templates(request, template_name="theme_editor/original_templates.html"):

    selected_theme = request.GET.get("theme_edit", get_theme())
    if not is_valid_theme(selected_theme):
        raise Http404(_('Specified theme does not exist'))
    if is_theme_read_only(selected_theme):
        raise Http403

    app = request.GET.get("app", None)

    current_dir = request.GET.get("dir", '')
    if current_dir:
        current_dir = current_dir.replace('\\', '/')
        current_dir = current_dir.strip('/')
        current_dir = current_dir.replace('////', '/')
        current_dir = current_dir.replace('///', '/')
        current_dir = current_dir.replace('//', '/')

    # if current_dir is a directory then append the
    # trailing slash so we can get the dirname below

    # get the previous directory name and path
    prev_dir = '/'
    prev_dir_name = 'original templates'
    current_dir_split = current_dir.split('/')
    if len(current_dir_split) > 1:
        prev_dir_name = current_dir_split[-2]
        current_dir_split.pop()
        prev_dir = '/'.join(current_dir_split)
    elif not current_dir_split[0]:
        prev_dir = ''

    if app in app_templates:
        root = app_templates[app]
    elif is_valid_theme(app):
        root = os.path.join(get_theme_root(app), 'templates')
    else:
        if '/' in app and app.split('/')[0] == 'builtin':
            builtin_base_name = app.split('/')[1]
            root = os.path.join(settings.TENDENCI_ROOT, "themes/{}/templates".format(builtin_base_name))
        else:
            raise Http404(_('Specified theme or app does not exist'))

    if not is_valid_path(root, current_dir):
        raise Http403

    dirs = get_dir_list(root, current_dir)
    files, non_editable_files = get_file_list(root, current_dir)
    return render_to_resp(request=request, template_name=template_name, context={
        'current_theme': selected_theme,
        'app': app,
        'current_dir': current_dir,
        'prev_dir_name': prev_dir_name,
        'prev_dir': prev_dir,
        'dirs': dirs,
        'files': files,
        'non_editable_files': non_editable_files,
    })
Exemple #4
0
def copy_to_theme(request):

    selected_theme = request.GET.get("theme_edit", get_theme())
    if not is_valid_theme(selected_theme):
        raise Http404(_('Specified theme does not exist'))
    if is_theme_read_only(selected_theme):
        raise Http403

    app = request.GET.get("app", None)

    current_dir = request.GET.get("dir", '')
    if current_dir:
        current_dir = current_dir.replace('\\', '/')
        current_dir = current_dir.strip('/')
        current_dir = current_dir.replace('////', '/')
        current_dir = current_dir.replace('///', '/')
        current_dir = current_dir.replace('//', '/')

    chosen_file = request.GET.get("file", '')
    if chosen_file:
        chosen_file = chosen_file.replace('\\', '/')
        chosen_file = chosen_file.strip('/')
        chosen_file = chosen_file.replace('////', '/')
        chosen_file = chosen_file.replace('///', '/')
        chosen_file = chosen_file.replace('//', '/')

    if app in app_templates:
        root = app_templates[app]
    elif is_valid_theme(app):
        root = os.path.join(get_theme_root(app), 'templates')
    else:
        if '/' in app and app.split('/')[0] == 'builtin':
            builtin_base_name = app.split('/')[1]
            root = os.path.join(
                settings.TENDENCI_ROOT,
                "themes/{}/templates".format(builtin_base_name))
        else:
            raise Http404(_('Specified theme or app does not exist'))

    if (not is_valid_path(root, current_dir) or
            not is_valid_path(root, os.path.join(current_dir, chosen_file))):
        raise Http403

    full_filename = os.path.join(root, current_dir, chosen_file)

    if not os.path.isfile(full_filename):
        raise Http404

    copy_file_to_theme(full_filename, selected_theme,
                       os.path.join('templates', current_dir), chosen_file)

    msg_string = 'Successfully copied %s/%s to theme' % (current_dir,
                                                         chosen_file)
    messages.add_message(request, messages.SUCCESS, _(msg_string))

    EventLog.objects.log()
    return redirect('theme_editor.editor')
Exemple #5
0
def delete_file(request):

    # if no permission; raise 403 exception
    if not has_perm(request.user, 'theme_editor.change_themefileversion'):
        raise Http403

    current_dir = request.GET.get("dir", '')
    if current_dir:
        current_dir = current_dir.replace('\\', '/')
        current_dir = current_dir.strip('/')
        current_dir = current_dir.replace('////', '/')
        current_dir = current_dir.replace('///', '/')
        current_dir = current_dir.replace('//', '/')

    if current_dir.startswith('plugins.'):
        current_dir = current_dir.split('plugins.')[1]

    chosen_file = request.GET.get("file", '')
    if chosen_file:
        chosen_file = chosen_file.replace('\\', '/')
        chosen_file = chosen_file.strip('/')
        chosen_file = chosen_file.replace('////', '/')
        chosen_file = chosen_file.replace('///', '/')
        chosen_file = chosen_file.replace('//', '/')

    full_filename = os.path.join(settings.PROJECT_ROOT, "themes", get_theme(),
                                 current_dir, chosen_file)

    if not os.path.isfile(full_filename):
        raise Http404

    os.remove(full_filename)

    if settings.USE_S3_STORAGE:
        delete_file_from_s3(file=settings.AWS_LOCATION + '/' + 'themes/' +
                            get_theme() + '/' + current_dir + chosen_file)

    msg_string = 'Successfully deleted %s/%s.' % (current_dir, chosen_file)
    messages.add_message(request, messages.SUCCESS, _(msg_string))

    EventLog.objects.log()
    return redirect('theme_editor.editor')
Exemple #6
0
def delete_file(request):

    # if no permission; raise 403 exception
    if not has_perm(request.user, 'theme_editor.change_themefileversion'):
        raise Http403

    current_dir = request.GET.get("dir", '')
    if current_dir:
        current_dir = current_dir.replace('\\', '/')
        current_dir = current_dir.strip('/')
        current_dir = current_dir.replace('////', '/')
        current_dir = current_dir.replace('///', '/')
        current_dir = current_dir.replace('//', '/')

    if current_dir.startswith('plugins.'):
        current_dir = current_dir.split('plugins.')[1]

    chosen_file = request.GET.get("file", '')
    if chosen_file:
        chosen_file = chosen_file.replace('\\', '/')
        chosen_file = chosen_file.strip('/')
        chosen_file = chosen_file.replace('////', '/')
        chosen_file = chosen_file.replace('///', '/')
        chosen_file = chosen_file.replace('//', '/')

    full_filename = os.path.join(settings.PROJECT_ROOT, "themes",
        get_theme(), current_dir,
        chosen_file)

    if not os.path.isfile(full_filename):
        raise Http404

    os.remove(full_filename)

    if settings.USE_S3_STORAGE:
        delete_file_from_s3(file=settings.AWS_LOCATION + '/' + 'themes/' + get_theme() + '/' + current_dir + chosen_file)

    msg_string = 'Successfully deleted %s/%s.' % (current_dir, chosen_file)
    messages.add_message(request, messages.SUCCESS, _(msg_string))

    EventLog.objects.log()
    return redirect('theme_editor.editor')
Exemple #7
0
    def save(self,
             request,
             file_relative_path,
             ROOT_DIR=THEME_ROOT,
             ORIG_ROOT_DIR=THEME_ROOT):
        content = self.cleaned_data["content"]
        file_path = (os.path.join(ROOT_DIR,
                                  file_relative_path)).replace("\\", "/")

        if settings.USE_S3_THEME:
            file_path = (os.path.join(ORIG_ROOT_DIR,
                                      file_relative_path)).replace("\\", "/")

        # write the theme file locally in case it was wiped by a restart
        if settings.USE_S3_THEME and not os.path.isfile(file_path):
            file_dir = os.path.dirname(file_path)
            if not os.path.isdir(file_dir):
                # if directory does not exist, create it
                os.makedirs(file_dir)
            new_file = open(file_path, 'w')
            new_file.write('')
            new_file.close()

        if os.path.isfile(file_path) and content != "":
            archive_file(request, file_relative_path, ROOT_DIR=ORIG_ROOT_DIR)

            # Save the file locally no matter the theme location.
            # The save to S3 reads from the local file, so we need to save it first.
            f = codecs.open(file_path, 'w', 'utf-8', 'replace')
            file = File(f)
            file.write(content)
            file.close()

            if settings.USE_S3_THEME:
                # copy to s3 storage
                if os.path.splitext(file_path)[1] == '.html':
                    public = False
                else:
                    public = True
                save_file_to_s3(file_path, public=public)

                cache_key = ".".join([
                    settings.SITE_CACHE_KEY, 'theme',
                    "%s/%s" % (get_theme(), file_relative_path)
                ])
                cache.delete(cache_key)

                if hasattr(settings,
                           'REMOTE_DEPLOY_URL') and settings.REMOTE_DEPLOY_URL:
                    urllib.urlopen(settings.REMOTE_DEPLOY_URL)

            return True
        else:
            return False
Exemple #8
0
    def get_template_sources(self, template_name, template_dirs=None):
        """
        Return possible absolute paths to "template_name" in the current theme
        and any themes it inherits from.
        Any paths that don't lie inside one of the template dirs are excluded
        from the result set for security reasons.
        """
        request = get_current_request()
        mobile = (request and request.mobile)

        active_theme = get_active_theme()
        theme = get_theme(active_theme)
        cached_theme, theme_search_info = self.cached_theme_search_info

        # If the theme changed or the user is previewing a different theme,
        # recalculate theme_search_info.
        # Note that this Loader instance may be shared between multiple threads,
        # so you must be careful when reading/writing
        # self.cached_theme_search_info to ensure that writes in one thread
        # cannot cause unexpected behavior in another thread that is
        # reading/writing self.cached_theme_search_info at the same time.
        if cached_theme != theme:
            theme_search_info = []
            for cur_theme in get_theme_search_order(theme):
                if is_builtin_theme(cur_theme) or not settings.USE_S3_THEME:
                    theme_search_info.append(
                        (cur_theme, get_theme_root(cur_theme), False))
                else:
                    theme_search_info.append((cur_theme, cur_theme, True))
            if theme == active_theme:
                self.cached_theme_search_info = (theme, theme_search_info)

        for cur_theme, cur_theme_root, use_s3_theme in theme_search_info:
            for template_path in (['mobile', 'templates']
                                  if mobile else ['templates']):
                if not use_s3_theme:
                    try:
                        template_file = safe_join(cur_theme_root,
                                                  template_path, template_name)
                    except SuspiciousFileOperation:
                        # The joined path was located outside of template_path,
                        # although it might be inside another one, so this isn't
                        # fatal.
                        continue
                else:
                    template_file = os.path.join(cur_theme_root, template_path,
                                                 template_name)
                origin = Origin(name=template_file,
                                template_name=template_name,
                                loader=self)
                origin.theme = cur_theme
                origin.use_s3_theme = use_s3_theme
                yield origin
Exemple #9
0
def delete_file(request):

    selected_theme = request.GET.get("theme_edit", get_theme())
    if not is_valid_theme(selected_theme):
        raise Http404(_('Specified theme does not exist'))
    if is_theme_read_only(selected_theme):
        raise Http403

    current_dir = request.GET.get("dir", '')
    if current_dir:
        current_dir = current_dir.replace('\\', '/')
        current_dir = current_dir.strip('/')
        current_dir = current_dir.replace('////', '/')
        current_dir = current_dir.replace('///', '/')
        current_dir = current_dir.replace('//', '/')

    if current_dir.startswith('plugins.'):
        current_dir = current_dir.split('plugins.')[1]

    chosen_file = request.GET.get("file", '')
    if chosen_file:
        chosen_file = chosen_file.replace('\\', '/')
        chosen_file = chosen_file.strip('/')
        chosen_file = chosen_file.replace('////', '/')
        chosen_file = chosen_file.replace('///', '/')
        chosen_file = chosen_file.replace('//', '/')

    theme_root = get_theme_root(selected_theme)

    if (not is_valid_path(theme_root, current_dir) or not is_valid_path(
            theme_root, os.path.join(current_dir, chosen_file))):
        raise Http403

    full_filename = os.path.join(theme_root, current_dir, chosen_file)

    if not os.path.isfile(full_filename):
        raise Http404

    os.remove(full_filename)

    if settings.USE_S3_STORAGE:
        s3_path = selected_theme + '/' + current_dir + chosen_file
        s3_full_path = settings.AWS_LOCATION + '/' + settings.THEME_S3_PATH + '/' + s3_path
        delete_file_from_s3(file=s3_full_path)
        cache_key = ".".join([settings.SITE_CACHE_KEY, 'theme', s3_path])
        cache.delete(cache_key)

    msg_string = 'Successfully deleted %s/%s.' % (current_dir, chosen_file)
    messages.add_message(request, messages.SUCCESS, _(msg_string))

    EventLog.objects.log()
    return redirect('theme_editor.editor')
Exemple #10
0
def create_new_template(request, form_class=AddTemplateForm):
    """
    Create a new blank template for a given template name
    """
    selected_theme = request.GET.get("theme_edit", get_theme())
    if not is_valid_theme(selected_theme):
        raise Http404(_('Specified theme does not exist'))
    if is_theme_read_only(selected_theme):
        raise Http403

    form = form_class(request.POST or None)
    ret_dict = {'created': False, 'err': ''}

    if form.is_valid():
        template_name = form.cleaned_data['template_name'].strip()
        template_full_name = 'default-%s.html' % template_name
        existing_templates = [t[0] for t in get_template_list()]
        if template_full_name not in existing_templates:
            # create a new template and assign default content
            theme_root = get_theme_root(selected_theme)
            template_dir = os.path.join(theme_root, 'templates')
            template_full_path = os.path.join(template_dir, template_full_name)
            # grab the content from the new-default-template.html
            # first check if there is a customized one on the site
            default_template_name = 'new-default-template.html'
            default_template_path = os.path.join(template_dir, 'theme_editor',
                                                 default_template_name)
            if not os.path.isfile(default_template_path):
                # no customized one found, use the default one
                default_template_path = os.path.join(
                    os.path.abspath(os.path.dirname(__file__)),
                    'templates/theme_editor', default_template_name)
            if os.path.isfile(default_template_path):
                default_content = open(default_template_path).read()
            else:
                default_content = ''
            with open(template_full_path, 'w') as f:
                f.write(default_content)
            if settings.USE_S3_STORAGE:
                s3_path = os.path.join(settings.THEME_S3_PATH, selected_theme,
                                       'templates', template_full_name)
                save_file_to_s3(template_full_path,
                                dest_path=s3_path,
                                public=False)
            ret_dict['created'] = True
            ret_dict['template_name'] = template_full_name
        else:
            ret_dict['err'] = _('Template "%(name)s" already exists' %
                                {'name': template_full_name})

    return HttpResponse(json.dumps(ret_dict))
Exemple #11
0
def app_list(request, template_name="theme_editor/app_list.html"):

    selected_theme = request.GET.get("theme_edit", get_theme())
    if not is_valid_theme(selected_theme):
        raise Http404(_('Specified theme does not exist'))
    if is_theme_read_only(selected_theme):
        raise Http403

    theme_list = get_theme_search_order(selected_theme)[1:]
    app_list = app_templates.keys()
    return render_to_resp(request=request, template_name=template_name, context={
        'current_theme': selected_theme,
        'apps': theme_list + sorted(app_list, key=lambda app: app[0]),
    })
Exemple #12
0
    def save(self, request, file_relative_path, ROOT_DIR=THEME_ROOT, ORIG_ROOT_DIR=THEME_ROOT):
        content = self.cleaned_data["content"]
        file_path = (os.path.join(ROOT_DIR, file_relative_path)).replace("\\", "/")

        if settings.USE_S3_THEME:
            file_path = (os.path.join(ORIG_ROOT_DIR, file_relative_path)).replace("\\", "/")

        # write the theme file locally in case it was wiped by a restart
        if settings.USE_S3_THEME and not os.path.isfile(file_path):
            file_dir = os.path.dirname(file_path)
            if not os.path.isdir(file_dir):
                # if directory does not exist, create it
                os.makedirs(file_dir)
            new_file = open(file_path, 'w')
            new_file.write('')
            new_file.close()

        if os.path.isfile(file_path) and content != "":
            archive_file(request, file_relative_path, ROOT_DIR=ORIG_ROOT_DIR)

            # Save the file locally no matter the theme location.
            # The save to S3 reads from the local file, so we need to save it first.
            f = codecs.open(file_path, 'w', 'utf-8', 'replace')
            file = File(f)
            file.write(content)
            file.close()

            if settings.USE_S3_THEME:
                # copy to s3 storage
                if os.path.splitext(file_path)[1] == '.html':
                    public = False
                else:
                    public = True
                save_file_to_s3(file_path, public=public)

                cache_key = ".".join([settings.SITE_CACHE_KEY, 'theme', "%s/%s" % (get_theme(), file_relative_path)])
                cache.delete(cache_key)

                if hasattr(settings, 'REMOTE_DEPLOY_URL') and settings.REMOTE_DEPLOY_URL:
                    urllib.urlopen(settings.REMOTE_DEPLOY_URL)

            return True
        else:
            return False
Exemple #13
0
def theme(request):
    context = {}

    if 'theme' in request.GET and request.user.profile.is_superuser:
        theme = request.GET.get('theme')
        if theme:
            request.session['theme'] = theme
        elif 'theme' in request.session:
            del request.session['theme']

    context['ACTIVE_THEME'] = get_active_theme()
    context['THEME'] = theme = get_theme(context['ACTIVE_THEME'])

    context['THEME_INFO'] = get_theme_info(theme)

    # Backward compatibility for old themes
    def warn_theme_urls(value):
        warn("{{ THEME_URL }}media/<path> is deprecated, use {% static '<path>' %} instead", DeprecationWarning)
        return value
    if is_builtin_theme(theme):
        theme_url = '%sthemes/%s/'%(settings.STATIC_URL, get_builtin_theme_dir(theme))
        def warn_theme_url(value=theme_url):  # noqa: E306
            return warn_theme_urls(value)
        context['THEME_URL'] = warn_theme_url
    elif settings.USE_S3_STORAGE:
        theme_url = '%s/%s/%s/themes/%s/'%(
            settings.S3_ROOT_URL, settings.AWS_STORAGE_BUCKET_NAME, settings.AWS_LOCATION, theme)
        def warn_theme_url(value=theme_url):  # noqa: E306
            return warn_theme_urls(value)
        context['THEME_URL'] = warn_theme_url
    else:
        theme_url = '/themes/'+theme+'/'
        def warn_theme_url(value=theme_url):  # noqa: E306
            return warn_theme_urls(value)
        context['THEME_URL'] = warn_theme_url
    local_theme_url = '/themes/'+theme+'/'
    def warn_local_theme_url(value=local_theme_url):  # noqa: E306
        warn("{{ LOCAL_THEME_URL }}media/<path> is deprecated, use {% local_static '<path>' %} instead", DeprecationWarning)
        return value
    context['LOCAL_THEME_URL'] = warn_local_theme_url

    return context
Exemple #14
0
def theme_delete(request):
    if not request.user.profile.is_superuser:
        raise Http403

    selected_theme = request.GET.get("theme_edit", get_theme())
    if not is_valid_theme(selected_theme):
        raise Http404(_('Specified theme does not exist'))
    if is_theme_read_only(selected_theme):
        raise Http403

    shutil.rmtree(get_theme_root(selected_theme))

    if settings.USE_S3_STORAGE:
        delete_file_from_s3(file=settings.AWS_LOCATION + '/' + settings.THEME_S3_PATH + '/' + selected_theme)

    msg_string = 'Successfully deleted %s.' % (selected_theme)
    messages.add_message(request, messages.SUCCESS, _(msg_string))

    EventLog.objects.log()
    return redirect('theme_editor.editor')
Exemple #15
0
def get_file_content(file, ROOT_DIR=THEME_ROOT):
    """
    Get the content from the file that selected from
    the navigation
    """
    content = ''

    if settings.USE_S3_THEME:
        try:
            theme = get_theme()
            content = read_theme_file_from_s3(os.path.join(theme, file))
        except:
            pass

    if not content:
        current_file = os.path.join(ROOT_DIR, file)
        if os.path.isfile(current_file):
            fd = open(current_file, 'r')
            content = fd.read()
            fd.close()
    return content
Exemple #16
0
def get_file_content(file, ROOT_DIR=THEME_ROOT):
    """
    Get the content from the file that selected from
    the navigation
    """
    content = ''

    if settings.USE_S3_THEME:
        try:
            theme = get_theme()
            content = read_theme_file_from_s3(os.path.join(theme, file))
        except:
            pass

    if not content:
        current_file = os.path.join(ROOT_DIR, file)
        if os.path.isfile(current_file):
            fd = open(current_file, 'r')
            content = fd.read()
            fd.close()
    return content
Exemple #17
0
def edit_file(request,
              form_class=FileForm,
              template_name="theme_editor/index.html"):

    if not has_perm(request.user, 'theme_editor.view_themefileversion'):
        raise Http403

    selected_theme = request.GET.get("theme_edit", get_theme())
    original_theme_root = os.path.join(settings.ORIGINAL_THEMES_DIR,
                                       selected_theme)
    if settings.USE_S3_THEME:
        theme_root = os.path.join(settings.THEME_S3_PATH, selected_theme)
    else:
        theme_root = os.path.join(settings.ORIGINAL_THEMES_DIR, selected_theme)

    # get the default file and clean up any input
    default_file = request.GET.get("file", DEFAULT_FILE)

    if default_file:
        default_file = default_file.replace('\\', '/')
        default_file = default_file.strip('/')
        default_file = default_file.replace('////', '/')
        default_file = default_file.replace('///', '/')
        default_file = default_file.replace('//', '/')

    is_file = qstr_is_file(default_file, ROOT_DIR=theme_root)
    is_dir = qstr_is_dir(default_file, ROOT_DIR=theme_root)

    if is_file:
        pass
    elif is_dir:
        # if default_file is a directory then append the
        # trailing slash so we can get the dirname below
        default_file = '%s/' % default_file
    else:
        # if the default_file is not a directory or file within
        # the themes folder then return a 404
        raise Http404(
            _("Custom template not found. Make sure you've copied over the themes to the THEME_DIR."
              ))

    # get the current file name
    current_file = os.path.basename(default_file)

    # get file ext
    name = current_file.split('/')[-1]
    ext = name.split('.')[-1]
    stylesheets = ['css', 'less']

    # get the present working directory
    # and make sure they cannot list root
    pwd = os.path.dirname(default_file)
    if pwd == '/':
        pwd = ''

    current_file_path = os.path.join(pwd, current_file)

    # get the previous directory name and path
    prev_dir = '/'
    prev_dir_name = 'theme base'
    pwd_split = pwd.split('/')
    if len(pwd_split) > 1:
        prev_dir_name = pwd_split[-2]
        pwd_split.pop()
        prev_dir = '/'.join(pwd_split)
    elif not pwd_split[0]:
        prev_dir = ''

    # get the direcory list
    dirs = get_dir_list(pwd, ROOT_DIR=theme_root)

    # get the file list
    files, non_editable_files = get_file_list(pwd, ROOT_DIR=theme_root)

    all_files_folders = get_all_files_list(ROOT_DIR=theme_root)

    # non-deletable files
    non_deletable_files = [
        'homepage.html', 'default.html', 'footer.html', 'header.html',
        'sidebar.html', 'nav.html', 'styles.less', 'styles.css'
    ]

    # get the number of themes in the themes directory on the site
    theme_choices = [i for i in theme_choice_list()]
    theme_count = len(theme_choices)

    # get a list of revisions
    archives = ThemeFileVersion.objects.filter(
        relative_file_path=default_file).order_by("-create_dt")

    if request.is_ajax() and request.method == "POST":
        file_form = form_class(request.POST)
        response_status = 'FAIL'
        response_message = _('Cannot update file.')
        if file_form.is_valid():
            if file_form.save(request,
                              default_file,
                              ROOT_DIR=theme_root,
                              ORIG_ROOT_DIR=original_theme_root):
                response_status = 'SUCCESS'
                response_message = unicode(_('Your changes have been saved.'))
                EventLog.objects.log()

        response = json.dumps({
            'status': response_status,
            'message': response_message
        })
        return HttpResponse(response, content_type="application/json")

    content = get_file_content(default_file, ROOT_DIR=theme_root)
    file_form = form_class({"content": content, "rf_path": default_file})

    theme_form = ThemeSelectForm(initial={'theme_edit': selected_theme})

    return render_to_response(template_name, {
        'file_form': file_form,
        'theme_form': theme_form,
        'current_theme': selected_theme,
        'current_file_path': current_file_path,
        'current_file': current_file,
        'prev_dir_name': prev_dir_name,
        'prev_dir': prev_dir,
        'pwd': pwd,
        'dirs': dirs,
        'files': files,
        'non_editable_files': non_editable_files,
        'non_deletable_files': non_deletable_files,
        'theme_count': theme_count,
        'archives': archives,
        'is_file': is_file,
        'is_dir': is_dir,
        'all_files_folders': all_files_folders,
        'ext': ext,
        'stylesheets': stylesheets
    },
                              context_instance=RequestContext(request))
Exemple #18
0
def edit_file(request,
              form_class=FileForm,
              template_name="theme_editor/index.html"):

    selected_theme = request.GET.get("theme_edit", get_theme())
    if not is_valid_theme(selected_theme):
        raise Http404(_('Specified theme does not exist'))

    # get the default file and clean up any input
    default_file = request.GET.get("file", DEFAULT_FILE)
    if default_file:
        default_file = default_file.replace('\\', '/')
        default_file = default_file.strip('/')
        default_file = default_file.replace('////', '/')
        default_file = default_file.replace('///', '/')
        default_file = default_file.replace('//', '/')

    theme_root = get_theme_root(selected_theme)
    if not is_valid_path(theme_root, default_file):
        raise Http403

    theme_read_only = is_theme_read_only(selected_theme)

    if request.is_ajax() and request.method == "POST":
        if theme_read_only:
            raise Http403
        file_form = form_class(request.POST)
        response_status = 'FAIL'
        response_message = _('Cannot update file.')
        if file_form.is_valid():
            if file_form.save(theme_root, selected_theme, default_file,
                              request):
                response_status = 'SUCCESS'
                response_message = str(_('Your changes have been saved.'))
                EventLog.objects.log()
        response = json.dumps({
            'status': response_status,
            'message': response_message
        })
        return HttpResponse(response, content_type='application/json')

    is_file = os.path.isfile(os.path.join(theme_root, default_file))
    is_dir = os.path.isdir(os.path.join(theme_root, default_file))
    if is_file:
        pass
    elif is_dir:
        # if default_file is a directory then append the
        # trailing slash so we can get the dirname below
        default_file = '%s/' % default_file
    else:
        # if the default_file is not a directory or file within
        # the themes folder then return a 404
        raise Http404(
            _("Custom template not found. Make sure you've copied over the themes to the THEME_DIR."
              ))

    # get the current file name
    current_file = os.path.basename(default_file)

    # get file ext
    name = current_file.split('/')[-1]
    ext = name.split('.')[-1]
    stylesheets = ['css', 'less']

    # get the present working directory
    # and make sure they cannot list root
    pwd = os.path.dirname(default_file)
    if pwd == '/':
        pwd = ''
    # make sure the path is still valid after stripping off the file name
    if not is_valid_path(theme_root, pwd):
        raise Http403

    current_file_path = os.path.join(pwd, current_file)

    # get the previous directory name and path
    prev_dir = '/'
    prev_dir_name = 'theme base'
    pwd_split = pwd.split('/')
    if len(pwd_split) > 1:
        prev_dir_name = pwd_split[-2]
        pwd_split.pop()
        prev_dir = '/'.join(pwd_split)
    elif not pwd_split[0]:
        prev_dir = ''

    # get the directory list
    dirs = get_dir_list(theme_root, pwd)

    # get the file list
    files, non_editable_files = get_file_list(theme_root, pwd)

    all_files_folders = get_all_files_list(theme_root, selected_theme)

    # non-deletable files
    non_deletable_files = [
        'homepage.html', 'default.html', 'footer.html', 'header.html',
        'sidebar.html', 'nav.html', 'styles.less', 'styles.css'
    ]

    # get the number of themes in the themes directory on the site
    theme_count = len([i for i in theme_choices()])

    # get a list of revisions
    archives = ThemeFileVersion.objects.filter(
        relative_file_path=current_file_path).order_by("-create_dt")

    # New templates created by clicking the New Template" button are blank.
    # Add a space for the blank template to make it editable.
    content = get_file_content(theme_root, selected_theme,
                               current_file_path) or ' '
    file_form = form_class({'content': content})
    theme_form = ThemeSelectForm(initial={'theme_edit': selected_theme})

    return render_to_resp(request=request,
                          template_name=template_name,
                          context={
                              'file_form': file_form,
                              'theme_form': theme_form,
                              'current_theme': selected_theme,
                              'current_file_path': current_file_path,
                              'current_file': current_file,
                              'prev_dir_name': prev_dir_name,
                              'prev_dir': prev_dir,
                              'pwd': pwd,
                              'dirs': dirs,
                              'files': files,
                              'non_editable_files': non_editable_files,
                              'non_deletable_files': non_deletable_files,
                              'theme_count': theme_count,
                              'archives': archives,
                              'is_file': is_file,
                              'is_dir': is_dir,
                              'theme_read_only': theme_read_only,
                              'can_copy_theme':
                              (not is_base_theme(selected_theme)),
                              'all_files_folders': all_files_folders,
                              'ext': ext,
                              'stylesheets': stylesheets,
                          })
Exemple #19
0
def get_all_files_list(ROOT_DIR=THEME_ROOT):
    """
    Get a list of files and folders from within
    the theme folder
    """
    files_folders = {}
    root_dir = os.path.join(ROOT_DIR)

    start = root_dir.rfind(os.sep) + 1
    for path, dirs, files in os.walk(root_dir):
        subdir = {'contents': []}
        folders = path[start:].split(os.sep)
        for f in files:
            editable = False
            if os.path.splitext(os.path.join(path, f))[1] in ALLOWED_EXTENSIONS:
                editable = True

            # Hide hidden folders
            if not f.startswith('.'):
                subdir['contents'].append({'name': f, 'path': os.path.join(path[len(root_dir) + 1:], f), 'editable': editable})

        subdir['contents'] = sorted(subdir['contents'], key=itemgetter('name'))
        parent = reduce(dict.get, folders[:-1], files_folders)

        # Hide hidden folders
        if not folders[-1].startswith('.'):
            parent[folders[-1]] = subdir

        for parent in files_folders:
            # Hide hidden folders
            if not path.split(os.sep)[-1].startswith('.'):
                subdir['contents'].append({'folder_path': path})

    if settings.USE_S3_THEME:
        s3_files_folders = {'contents': []}
        theme_folder = "%s/%s" % (settings.THEME_S3_PATH, get_theme())
        conn = boto.connect_s3(settings.AWS_ACCESS_KEY_ID,
                               settings.AWS_SECRET_ACCESS_KEY)
        bucket = conn.get_bucket(settings.AWS_STORAGE_BUCKET_NAME)

        for item in bucket.list(prefix=theme_folder):

            editable = False
            if os.path.splitext(item.name)[1] in ALLOWED_EXTENSIONS:
                editable = True

            file_path = item.name.replace(theme_folder, '').lstrip('/')
            path_split = file_path.split('/')
            splits = len(path_split)

            if splits == 1:
                s3_files_folders['contents'].append({
                        'name': path_split[0],
                        'path': file_path,
                        'editable': editable})
            elif splits == 2:
                if not path_split[0] in s3_files_folders:
                    s3_files_folders[path_split[0]] = {'contents': [{'folder_path': "/".join(path_split[:-1])}]}

                s3_files_folders[path_split[0]]['contents'].append({
                        'name': path_split[1],
                        'path': file_path,
                        'editable': editable})
            elif splits == 3:
                if not path_split[0] in s3_files_folders:
                    s3_files_folders[path_split[0]] = {'contents': [{'folder_path': "/".join(path_split[:-1])}]}

                if not path_split[1] in s3_files_folders[path_split[0]]:
                    s3_files_folders[path_split[0]][path_split[1]] = {'contents': [{'folder_path': "/".join(path_split[:-1])}]}

                s3_files_folders[path_split[0]][path_split[1]]['contents'].append({
                        'name': path_split[2],
                        'path': file_path,
                        'editable': editable})
            elif splits == 4:
                if not path_split[0] in s3_files_folders:
                    s3_files_folders[path_split[0]] = {'contents': [{'folder_path': "/".join(path_split[:-1])}]}

                if not path_split[1] in s3_files_folders[path_split[0]]:
                    s3_files_folders[path_split[0]][path_split[1]] = {'contents': [{'folder_path': "/".join(path_split[:-1])}]}

                if not path_split[2] in s3_files_folders[path_split[0]][path_split[1]]:
                    s3_files_folders[path_split[0]][path_split[1]][path_split[2]] = {'contents': [{'folder_path': "/".join(path_split[:-1])}]}

                s3_files_folders[path_split[0]][path_split[1]][path_split[2]]['contents'].append({
                        'name': path_split[3],
                        'path': file_path,
                        'editable': editable})

        return {get_theme(): s3_files_folders}

    return files_folders
Exemple #20
0
def get_all_files_list(ROOT_DIR=THEME_ROOT):
    """
    Get a list of files and folders from within
    the theme folder
    """
    files_folders = {}
    root_dir = os.path.join(ROOT_DIR)

    start = root_dir.rfind(os.sep) + 1
    for path, dirs, files in os.walk(root_dir):
        folders = path[start:].split(os.sep)

        # Hide hidden folders and folders within hidden folders
        if any(folder.startswith('.') for folder in folders):
            continue

        subdir = {'contents': []}
        for f in files:
            editable = False
            if os.path.splitext(os.path.join(path,
                                             f))[1] in ALLOWED_EXTENSIONS:
                editable = True

            # Hide hidden files
            if not f.startswith('.'):
                subdir['contents'].append({
                    'name':
                    f,
                    'path':
                    os.path.join(path[len(root_dir) + 1:], f),
                    'editable':
                    editable
                })

        subdir['contents'] = sorted(subdir['contents'], key=itemgetter('name'))
        subdir['contents'].append({'folder_path': path})
        parent = reduce(dict.get, folders[:-1], files_folders)
        parent[folders[-1]] = subdir

    if settings.USE_S3_THEME:
        s3_files_folders = {'contents': []}
        theme_folder = "%s/%s" % (settings.THEME_S3_PATH, get_theme())
        conn = boto.connect_s3(settings.AWS_ACCESS_KEY_ID,
                               settings.AWS_SECRET_ACCESS_KEY)
        bucket = conn.get_bucket(settings.AWS_STORAGE_BUCKET_NAME)

        for item in bucket.list(prefix=theme_folder):

            editable = False
            if os.path.splitext(item.name)[1] in ALLOWED_EXTENSIONS:
                editable = True

            file_path = item.name.replace(theme_folder, '').lstrip('/')
            path_split = file_path.split('/')
            splits = len(path_split)

            if splits == 1:
                s3_files_folders['contents'].append({
                    'name': path_split[0],
                    'path': file_path,
                    'editable': editable
                })
            elif splits == 2:
                if not path_split[0] in s3_files_folders:
                    s3_files_folders[path_split[0]] = {
                        'contents': [{
                            'folder_path': "/".join(path_split[:-1])
                        }]
                    }

                s3_files_folders[path_split[0]]['contents'].append({
                    'name':
                    path_split[1],
                    'path':
                    file_path,
                    'editable':
                    editable
                })
            elif splits == 3:
                if not path_split[0] in s3_files_folders:
                    s3_files_folders[path_split[0]] = {
                        'contents': [{
                            'folder_path': "/".join(path_split[:-1])
                        }]
                    }

                if not path_split[1] in s3_files_folders[path_split[0]]:
                    s3_files_folders[path_split[0]][path_split[1]] = {
                        'contents': [{
                            'folder_path': "/".join(path_split[:-1])
                        }]
                    }

                s3_files_folders[path_split[0]][
                    path_split[1]]['contents'].append({
                        'name': path_split[2],
                        'path': file_path,
                        'editable': editable
                    })
            elif splits == 4:
                if not path_split[0] in s3_files_folders:
                    s3_files_folders[path_split[0]] = {
                        'contents': [{
                            'folder_path': "/".join(path_split[:-1])
                        }]
                    }

                if not path_split[1] in s3_files_folders[path_split[0]]:
                    s3_files_folders[path_split[0]][path_split[1]] = {
                        'contents': [{
                            'folder_path': "/".join(path_split[:-1])
                        }]
                    }

                if not path_split[2] in s3_files_folders[path_split[0]][
                        path_split[1]]:
                    s3_files_folders[path_split[0]][path_split[1]][
                        path_split[2]] = {
                            'contents': [{
                                'folder_path':
                                "/".join(path_split[:-1])
                            }]
                        }

                s3_files_folders[path_split[0]][path_split[1]][
                    path_split[2]]['contents'].append({
                        'name': path_split[3],
                        'path': file_path,
                        'editable': editable
                    })

        return {get_theme(): s3_files_folders}

    return files_folders
Exemple #21
0
    def handle_simple(cls, path, local_only, template=None, theme=None):

        active_theme = get_active_theme()
        theme = get_theme(active_theme)
        global _cached_theme_search_info
        cached_theme, theme_search_info = _cached_theme_search_info

        # If the theme changed or the user is previewing a different theme,
        # update _cached_theme_search_info.
        # Note that _cached_theme_search_info may be shared between multiple
        # threads, so you must be careful when reading/writing
        # _cached_theme_search_info to ensure that writes in one thread cannot
        # cause unexpected behavior in another thread that is reading/writing
        # _cached_theme_search_info at the same time.
        if cached_theme != theme:
            theme_search_info = []
            for cur_theme in get_theme_search_order(theme):
                if is_builtin_theme(cur_theme):
                    cur_theme_dir = get_builtin_theme_dir(cur_theme)
                    static_path = os.path.join(settings.STATIC_ROOT, 'themes',
                                               cur_theme_dir)
                    if not os.path.isdir(static_path):
                        continue
                    local_static_url = '%sthemes/%s/' % (
                        settings.LOCAL_STATIC_URL, cur_theme_dir)
                    static_url = '%sthemes/%s/' % (settings.STATIC_URL,
                                                   cur_theme_dir)
                    theme_search_info.append(
                        (static_path, local_static_url, static_url))
                else:
                    cur_theme_root = get_theme_root(cur_theme)
                    for static_dir in ['media', 'static']:
                        static_path = os.path.join(cur_theme_root, static_dir)
                        if not os.path.isdir(static_path):
                            continue
                        local_static_url = static_url = '/themes/' + cur_theme + '/' + static_dir + '/'
                        if settings.USE_S3_STORAGE:
                            static_url = '%s/%s/%s/themes/%s/%s/' % (
                                settings.S3_ROOT_URL,
                                settings.AWS_STORAGE_BUCKET_NAME,
                                settings.AWS_LOCATION, cur_theme, static_dir)
                        theme_search_info.append(
                            (static_path, local_static_url, static_url))
            if theme == active_theme:
                _cached_theme_search_info = (theme, theme_search_info)

        # Search for static file in themes
        for static_path, local_static_url, static_url in theme_search_info:
            if not os.path.exists(os.path.join(static_path, path)):
                continue
            return urljoin((local_static_url if local_only else static_url),
                           quote(path))

        # Warn about static files that don't exist in either a theme or
        # STATIC_ROOT
        if not os.path.exists(os.path.join(settings.STATIC_ROOT, path)):
            if not template:
                call = ('local_static' if local_only else 'static')
                warn('%s() call references non-existent static path "%s"' %
                     (call, path))
            else:
                tag = ('{% local_static %}' if local_only else '{% static %}')
                theme_str = ('theme "%s"' %
                             (theme) if theme else 'an installed Django app')
                warn(
                    '%s in template "%s" in %s references non-existent static path "%s"'
                    % (tag, template, theme_str, path))

        # Handle {% local_static %} for files not found in a theme
        if local_only:
            return urljoin(settings.LOCAL_STATIC_URL, quote(path))

        # Default to standard Django {% static %} behavior
        return super(ThemeStaticNode, cls).handle_simple(path)
Exemple #22
0
def edit_file(request, form_class=FileForm, template_name="theme_editor/index.html"):

    if not has_perm(request.user, 'theme_editor.view_themefileversion'):
        raise Http403

    selected_theme = request.GET.get("theme_edit", get_theme())
    original_theme_root = os.path.join(settings.ORIGINAL_THEMES_DIR, selected_theme)
    if settings.USE_S3_THEME:
        theme_root = os.path.join(settings.THEME_S3_PATH, selected_theme)
    else:
        theme_root = os.path.join(settings.ORIGINAL_THEMES_DIR, selected_theme)

    # get the default file and clean up any input
    default_file = request.GET.get("file", DEFAULT_FILE)

    if default_file:
        default_file = default_file.replace('\\', '/')
        default_file = default_file.strip('/')
        default_file = default_file.replace('////', '/')
        default_file = default_file.replace('///', '/')
        default_file = default_file.replace('//', '/')

    is_file = qstr_is_file(default_file, ROOT_DIR=theme_root)
    is_dir = qstr_is_dir(default_file, ROOT_DIR=theme_root)

    if is_file:
        pass
    elif is_dir:
        # if default_file is a directory then append the
        # trailing slash so we can get the dirname below
        default_file = '%s/' % default_file
    else:
        # if the default_file is not a directory or file within
        # the themes folder then return a 404
        raise Http404(_("Custom template not found. Make sure you've copied over the themes to the THEME_DIR."))

    # get the current file name
    current_file = os.path.basename(default_file)

    # get file ext
    name = current_file.split('/')[-1]
    ext = name.split('.')[-1]
    stylesheets = ['css', 'less']

    # get the present working directory
    # and make sure they cannot list root
    pwd = os.path.dirname(default_file)
    if pwd == '/':
        pwd = ''

    current_file_path = os.path.join(pwd, current_file)

    # get the previous directory name and path
    prev_dir = '/'
    prev_dir_name = 'theme base'
    pwd_split = pwd.split('/')
    if len(pwd_split) > 1:
        prev_dir_name = pwd_split[-2]
        pwd_split.pop()
        prev_dir = '/'.join(pwd_split)
    elif not pwd_split[0]:
        prev_dir = ''

    # get the direcory list
    dirs = get_dir_list(pwd, ROOT_DIR=theme_root)

    # get the file list
    files, non_editable_files = get_file_list(pwd, ROOT_DIR=theme_root)

    all_files_folders = get_all_files_list(ROOT_DIR=theme_root)

    # non-deletable files
    non_deletable_files = ['homepage.html', 'default.html', 'footer.html', 'header.html', 'sidebar.html', 'nav.html', 'styles.less', 'styles.css']

    # get the number of themes in the themes directory on the site
    theme_choices = [ i for i in theme_choice_list()]
    theme_count = len(theme_choices)

    # get a list of revisions
    archives = ThemeFileVersion.objects.filter(relative_file_path=default_file).order_by("-create_dt")

    if request.is_ajax() and request.method == "POST":
        file_form = form_class(request.POST)
        response_status = 'FAIL'
        response_message = _('Cannot update file.')
        if file_form.is_valid():
            if file_form.save(request, default_file, ROOT_DIR=theme_root, ORIG_ROOT_DIR=original_theme_root):
                response_status = 'SUCCESS'
                response_message = unicode(_('Your changes have been saved.'))
                EventLog.objects.log()

        response = json.dumps({'status':response_status, 'message':response_message})
        return HttpResponse(response, content_type="application/json")

    content = get_file_content(default_file,  ROOT_DIR=theme_root)
    file_form = form_class({"content": content, "rf_path": default_file})

    theme_form = ThemeSelectForm(initial={'theme_edit': selected_theme})

    return render_to_response(template_name, {
        'file_form': file_form,
        'theme_form': theme_form,
        'current_theme': selected_theme,
        'current_file_path': current_file_path,
        'current_file': current_file,
        'prev_dir_name': prev_dir_name,
        'prev_dir': prev_dir,
        'pwd': pwd,
        'dirs': dirs,
        'files': files,
        'non_editable_files': non_editable_files,
        'non_deletable_files': non_deletable_files,
        'theme_count': theme_count,
        'archives': archives,
        'is_file': is_file,
        'is_dir': is_dir,
        'all_files_folders': all_files_folders,
        'ext' : ext,
        'stylesheets' : stylesheets
    }, context_instance=RequestContext(request))