<commit_before>import logging
import json
import os
import tarfile
import shutil
from tempfile import mkdtemp
from path import path

from django.conf import settings
from django.http import HttpResponse, HttpResponseBadRequest
from django.contrib.auth.decorators import login_required
from django_future.csrf import ensure_csrf_cookie
from django.core.urlresolvers import reverse
from django.core.servers.basehttp import FileWrapper
from django.core.files.temp import NamedTemporaryFile

from mitxmako.shortcuts import render_to_response
from cache_toolbox.core import del_cached_content
from auth.authz import create_all_course_groups

from xmodule.modulestore.xml_importer import import_from_xml
from xmodule.contentstore.django import contentstore
from xmodule.modulestore.xml_exporter import export_to_xml
from xmodule.modulestore.django import modulestore
from xmodule.modulestore import Location
from xmodule.contentstore.content import StaticContent
from xmodule.util.date_utils import get_default_time_display
from xmodule.modulestore import InvalidLocationError
from xmodule.exceptions import NotFoundError

from ..utils import get_url_reverse
from .access import get_location_and_verify_access


__all__ = ['asset_index', 'upload_asset', 'import_course', 'generate_export_course', 'export_course']


@login_required
@ensure_csrf_cookie
def asset_index(request, org, course, name):
    """
    Display an editable asset library

    org, course, name: Attributes of the Location for the item to edit
    """
    location = get_location_and_verify_access(request, org, course, name)

    upload_asset_callback_url = reverse('upload_asset', kwargs={
        'org': org,
        'course': course,
        'coursename': name
    })

    course_module = modulestore().get_item(location)

    course_reference = StaticContent.compute_location(org, course, name)
    assets = contentstore().get_all_content_for_course(course_reference)

    # sort in reverse upload date order
    assets = sorted(assets, key=lambda asset: asset['uploadDate'], reverse=True)

    asset_display = []
    for asset in assets:
        asset_id = asset['_id']
        display_info = {}
        display_info['displayname'] = asset['displayname']
        display_info['uploadDate'] = get_default_time_display(asset['uploadDate'])

        asset_location = StaticContent.compute_location(asset_id['org'], asset_id['course'], asset_id['name'])
        display_info['url'] = StaticContent.get_url_path_from_location(asset_location)

        # note, due to the schema change we may not have a 'thumbnail_location' in the result set
        _thumbnail_location = asset.get('thumbnail_location', None)
        thumbnail_location = Location(_thumbnail_location) if _thumbnail_location is not None else None
        display_info['thumb_url'] = StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_location is not None else None

        asset_display.append(display_info)

    return render_to_response('asset_index.html', {
        'context_course': course_module,
        'assets': asset_display,
        'upload_asset_callback_url': upload_asset_callback_url,
        'remove_asset_callback_url': reverse('remove_asset', kwargs={
            'org': org,
            'course': course,
            'name': name
        })
    })


@ensure_csrf_cookie
@login_required
def upload_asset(request, org, course, coursename):
    '''
    This method allows for POST uploading of files into the course asset library, which will
    be supported by GridFS in MongoDB.
    '''
    if request.method != 'POST':
        # (cdodge) @todo: Is there a way to do a - say - 'raise Http400'?
        return HttpResponseBadRequest()

    # construct a location from the passed in path
    location = get_location_and_verify_access(request, org, course, coursename)

    # Does the course actually exist?!? Get anything from it to prove its existance

    try:
        modulestore().get_item(location)
    except:
        # no return it as a Bad Request response
        logging.error('Could not find course' + location)
        return HttpResponseBadRequest()

    if 'file' not in request.FILES:
        return HttpResponseBadRequest()

    # compute a 'filename' which is similar to the location formatting, we're using the 'filename'
    # nomenclature since we're using a FileSystem paradigm here. We're just imposing
    # the Location string formatting expectations to keep things a bit more consistent
    upload_file = request.FILES['file']
    filename = upload_file.name
    mime_type = upload_file.content_type

    content_loc = StaticContent.compute_location(org, course, filename)

    chunked = upload_file.multiple_chunks()
    if chunked:
        content = StaticContent(content_loc, filename, mime_type, upload_file.chunks())
    else:
        content = StaticContent(content_loc, filename, mime_type, upload_file.read())

    thumbnail_content = None
    thumbnail_location = None

    # first let's see if a thumbnail can be created
    (thumbnail_content, thumbnail_location) = contentstore().generate_thumbnail(content,
                                                                                tempfile_path=None if not chunked else
                                                                                upload_file.temporary_file_path())

    # delete cached thumbnail even if one couldn't be created this time (else the old thumbnail will continue to show)
    del_cached_content(thumbnail_location)
    # now store thumbnail location only if we could create it
    if thumbnail_content is not None:
        content.thumbnail_location = thumbnail_location

    # then commit the content
    contentstore().save(content)
    del_cached_content(content.location)

    # readback the saved content - we need the database timestamp
    readback = contentstore().find(content.location)

    response_payload = {'displayname': content.name,
                        'uploadDate': get_default_time_display(readback.last_modified_at),
                        'url': StaticContent.get_url_path_from_location(content.location),
                        'thumb_url': StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_content is not None else None,
                        'msg': 'Upload completed'
                        }

    response = HttpResponse(json.dumps(response_payload))
    response['asset_url'] = StaticContent.get_url_path_from_location(content.location)
    return response


@ensure_csrf_cookie
@login_required
def remove_asset(request, org, course, name):
    '''
    This method will perform a 'soft-delete' of an asset, which is basically to copy the asset from
    the main GridFS collection and into a Trashcan
    '''
    get_location_and_verify_access(request, org, course, name)

    location = request.POST['location']

    # make sure the location is valid<commit_msg>return right mimetype from upload method.<commit_after>import logging
import json
import os
import tarfile
import shutil
from tempfile import mkdtemp
from path import path

from django.conf import settings
from django.http import HttpResponse, HttpResponseBadRequest
from django.contrib.auth.decorators import login_required
from django_future.csrf import ensure_csrf_cookie
from django.core.urlresolvers import reverse
from django.core.servers.basehttp import FileWrapper
from django.core.files.temp import NamedTemporaryFile

from mitxmako.shortcuts import render_to_response
from cache_toolbox.core import del_cached_content
from auth.authz import create_all_course_groups

from xmodule.modulestore.xml_importer import import_from_xml
from xmodule.contentstore.django import contentstore
from xmodule.modulestore.xml_exporter import export_to_xml
from xmodule.modulestore.django import modulestore
from xmodule.modulestore import Location
from xmodule.contentstore.content import StaticContent
from xmodule.util.date_utils import get_default_time_display
from xmodule.modulestore import InvalidLocationError
from xmodule.exceptions import NotFoundError

from ..utils import get_url_reverse
from .access import get_location_and_verify_access


__all__ = ['asset_index', 'upload_asset', 'import_course', 'generate_export_course', 'export_course']


@login_required
@ensure_csrf_cookie
def asset_index(request, org, course, name):
    """
    Display an editable asset library

    org, course, name: Attributes of the Location for the item to edit
    """
    location = get_location_and_verify_access(request, org, course, name)

    upload_asset_callback_url = reverse('upload_asset', kwargs={
        'org': org,
        'course': course,
        'coursename': name
    })

    course_module = modulestore().get_item(location)

    course_reference = StaticContent.compute_location(org, course, name)
    assets = contentstore().get_all_content_for_course(course_reference)

    # sort in reverse upload date order
    assets = sorted(assets, key=lambda asset: asset['uploadDate'], reverse=True)

    asset_display = []
    for asset in assets:
        asset_id = asset['_id']
        display_info = {}
        display_info['displayname'] = asset['displayname']
        display_info['uploadDate'] = get_default_time_display(asset['uploadDate'])

        asset_location = StaticContent.compute_location(asset_id['org'], asset_id['course'], asset_id['name'])
        display_info['url'] = StaticContent.get_url_path_from_location(asset_location)

        # note, due to the schema change we may not have a 'thumbnail_location' in the result set
        _thumbnail_location = asset.get('thumbnail_location', None)
        thumbnail_location = Location(_thumbnail_location) if _thumbnail_location is not None else None
        display_info['thumb_url'] = StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_location is not None else None

        asset_display.append(display_info)

    return render_to_response('asset_index.html', {
        'context_course': course_module,
        'assets': asset_display,
        'upload_asset_callback_url': upload_asset_callback_url,
        'remove_asset_callback_url': reverse('remove_asset', kwargs={
            'org': org,
            'course': course,
            'name': name
        })
    })


@ensure_csrf_cookie
@login_required
def upload_asset(request, org, course, coursename):
    '''
    This method allows for POST uploading of files into the course asset library, which will
    be supported by GridFS in MongoDB.
    '''
    if request.method != 'POST':
        # (cdodge) @todo: Is there a way to do a - say - 'raise Http400'?
        return HttpResponseBadRequest()

    # construct a location from the passed in path
    location = get_location_and_verify_access(request, org, course, coursename)

    # Does the course actually exist?!? Get anything from it to prove its existance

    try:
        modulestore().get_item(location)
    except:
        # no return it as a Bad Request response
        logging.error('Could not find course' + location)
        return HttpResponseBadRequest()

    if 'file' not in request.FILES:
        return HttpResponseBadRequest()

    # compute a 'filename' which is similar to the location formatting, we're using the 'filename'
    # nomenclature since we're using a FileSystem paradigm here. We're just imposing
    # the Location string formatting expectations to keep things a bit more consistent
    upload_file = request.FILES['file']
    filename = upload_file.name
    mime_type = upload_file.content_type

    content_loc = StaticContent.compute_location(org, course, filename)

    chunked = upload_file.multiple_chunks()
    if chunked:
        content = StaticContent(content_loc, filename, mime_type, upload_file.chunks())
    else:
        content = StaticContent(content_loc, filename, mime_type, upload_file.read())

    thumbnail_content = None
    thumbnail_location = None

    # first let's see if a thumbnail can be created
    (thumbnail_content, thumbnail_location) = contentstore().generate_thumbnail(content,
                                                                                tempfile_path=None if not chunked else
                                                                                upload_file.temporary_file_path())

    # delete cached thumbnail even if one couldn't be created this time (else the old thumbnail will continue to show)
    del_cached_content(thumbnail_location)
    # now store thumbnail location only if we could create it
    if thumbnail_content is not None:
        content.thumbnail_location = thumbnail_location

    # then commit the content
    contentstore().save(content)
    del_cached_content(content.location)

    # readback the saved content - we need the database timestamp
    readback = contentstore().find(content.location)

    response_payload = {'displayname': content.name,
                        'uploadDate': get_default_time_display(readback.last_modified_at),
                        'url': StaticContent.get_url_path_from_location(content.location),
                        'thumb_url': StaticContent.get_url_path_from_location(thumbnail_location) if thumbnail_content is not None else None,
                        'msg': 'Upload completed'
                        }

    response = HttpResponse(json.dumps(response_payload), mimetype="application/json")
    response['asset_url'] = StaticContent.get_url_path_from_location(content.location)
    return response


@ensure_csrf_cookie
@login_required
def remove_asset(request, org, course, name):
    '''
    This method will perform a 'soft-delete' of an asset, which is basically to copy the asset from
    the main GridFS collection and into a Trashcan
    '''
    get_location_and_verify_access(request, org, course, name)

    location = request.POST['location']

    # make sure the location is valid
{'fraction_non_alphanumeric': 0.07240014393666787, 'fraction_numerical': 0.0004318100035984167, 'mean_word_length': 3.5695494902992437, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 8}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6122815', 'n_tokens_mistral': 3784, 'n_tokens_neox': 3653, 'n_words': 1091}