<commit_before>from __future__ import absolute_import

from django.conf import settings
from django.template.defaultfilters import slugify

from zerver.lib.avatar import user_avatar_hash

from boto.s3.key import Key
from boto.s3.connection import S3Connection
from mimetypes import guess_type, guess_extension

import base64
import os

# Performance Note:
#
# For writing files to S3, the file could either be stored in RAM
# (if it is less than 2.5MiB or so) or an actual temporary file on disk.
#
# Because we set FILE_UPLOAD_MAX_MEMORY_SIZE to 0, only the latter case
# should occur in practice.
#
# This is great, because passing the pseudofile object that Django gives
# you to boto would be a pain.

# To come up with a s3 key we randomly generate a "directory". The "file
# name" is the original filename provided by the user run through Django's
# slugify.

def sanitize_name(name):
    split_name = name.split('.')
    base = ".".join(split_name[:-1])
    extension = split_name[-1]
    return slugify(base) + "." + slugify(extension)

def random_name(bytes=60):
    return base64.urlsafe_b64encode(os.urandom(bytes))

def upload_image_to_s3(
        bucket_name,
        file_name,
        content_type,
        user_profile,
        contents,
    ):

    conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
    key = Key(conn.get_bucket(bucket_name))
    key.key = file_name
    key.set_metadata("user_profile_id", str(user_profile.id))
    key.set_metadata("realm_id", str(user_profile.realm.id))

    if content_type:
        headers = {'Content-Type': content_type}
    else:
        headers = None

    key.set_contents_from_string(contents, headers=headers)

def get_file_info(request, user_file):
    uploaded_file_name = user_file.name
    content_type = request.GET.get('mimetype')
    if content_type is None:
        content_type = guess_type(uploaded_file_name)[0]
    else:
        uploaded_file_name = uploaded_file_name + guess_extension(content_type)
    return uploaded_file_name, content_type

def authed_upload_enabled(user_profile):
    return user_profile.realm.domain in ('zulip.com', 'squarespace.com')

def upload_message_image(uploaded_file_name, content_type, file_data, user_profile, private=None):
    if private is None:
        private = authed_upload_enabled(user_profile)
    if private:
        bucket_name = settings.S3_AUTH_UPLOADS_BUCKET
        s3_file_name = "/".join([
            str(user_profile.realm.id),
            random_name(18),
            sanitize_name(uploaded_file_name)
        ])
        url = "/user_uploads/%s" % (s3_file_name)
    else:
        bucket_name = settings.S3_BUCKET
        s3_file_name = "/".join([random_name(60), sanitize_name(uploaded_file_name)])
        url = "https://%s.s3.amazonaws.com/%s" % (bucket_name, s3_file_name)

    upload_image_to_s3(
            bucket_name,
            s3_file_name,
            content_type,
            user_profile,
            file_data
    )
    return url

def upload_message_image_through_web_client(request, user_file, user_profile, private=None):
    uploaded_file_name, content_type = get_file_info(request, user_file)
    return upload_message_image(uploaded_file_name, content_type, user_file.read(), user_profile, private)

def get_signed_upload_url(path):
    conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
    return conn.generate_url(15, 'GET', bucket=settings.S3_AUTH_UPLOADS_BUCKET, key=path)

def upload_avatar_image(user_file, user_profile, email):
    content_type = guess_type(user_file.name)[0]
    bucket_name = settings.S3_AVATAR_BUCKET
    s3_file_name = user_avatar_hash(email)
    upload_image_to_s3(
        bucket_name,
        s3_file_name,
        content_type,
        user_profile,
        user_file.read(),
    )
    # See avatar_url in avatar.py for URL.  (That code also handles the case
    # that users use gravatar.)
<commit_msg>Reduce the length of public upload URLs.<commit_after>from __future__ import absolute_import

from django.conf import settings
from django.template.defaultfilters import slugify

from zerver.lib.avatar import user_avatar_hash

from boto.s3.key import Key
from boto.s3.connection import S3Connection
from mimetypes import guess_type, guess_extension

import base64
import os

# Performance Note:
#
# For writing files to S3, the file could either be stored in RAM
# (if it is less than 2.5MiB or so) or an actual temporary file on disk.
#
# Because we set FILE_UPLOAD_MAX_MEMORY_SIZE to 0, only the latter case
# should occur in practice.
#
# This is great, because passing the pseudofile object that Django gives
# you to boto would be a pain.

# To come up with a s3 key we randomly generate a "directory". The "file
# name" is the original filename provided by the user run through Django's
# slugify.

def sanitize_name(name):
    split_name = name.split('.')
    base = ".".join(split_name[:-1])
    extension = split_name[-1]
    return slugify(base) + "." + slugify(extension)

def random_name(bytes=60):
    return base64.urlsafe_b64encode(os.urandom(bytes))

def upload_image_to_s3(
        bucket_name,
        file_name,
        content_type,
        user_profile,
        contents,
    ):

    conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
    key = Key(conn.get_bucket(bucket_name))
    key.key = file_name
    key.set_metadata("user_profile_id", str(user_profile.id))
    key.set_metadata("realm_id", str(user_profile.realm.id))

    if content_type:
        headers = {'Content-Type': content_type}
    else:
        headers = None

    key.set_contents_from_string(contents, headers=headers)

def get_file_info(request, user_file):
    uploaded_file_name = user_file.name
    content_type = request.GET.get('mimetype')
    if content_type is None:
        content_type = guess_type(uploaded_file_name)[0]
    else:
        uploaded_file_name = uploaded_file_name + guess_extension(content_type)
    return uploaded_file_name, content_type

def authed_upload_enabled(user_profile):
    return user_profile.realm.domain in ('zulip.com', 'squarespace.com')

def upload_message_image(uploaded_file_name, content_type, file_data, user_profile, private=None):
    if private is None:
        private = authed_upload_enabled(user_profile)
    if private:
        bucket_name = settings.S3_AUTH_UPLOADS_BUCKET
        s3_file_name = "/".join([
            str(user_profile.realm.id),
            random_name(18),
            sanitize_name(uploaded_file_name)
        ])
        url = "/user_uploads/%s" % (s3_file_name)
    else:
        bucket_name = settings.S3_BUCKET
        s3_file_name = "/".join([random_name(18), sanitize_name(uploaded_file_name)])
        url = "https://%s.s3.amazonaws.com/%s" % (bucket_name, s3_file_name)

    upload_image_to_s3(
            bucket_name,
            s3_file_name,
            content_type,
            user_profile,
            file_data
    )
    return url

def upload_message_image_through_web_client(request, user_file, user_profile, private=None):
    uploaded_file_name, content_type = get_file_info(request, user_file)
    return upload_message_image(uploaded_file_name, content_type, user_file.read(), user_profile, private)

def get_signed_upload_url(path):
    conn = S3Connection(settings.S3_KEY, settings.S3_SECRET_KEY)
    return conn.generate_url(15, 'GET', bucket=settings.S3_AUTH_UPLOADS_BUCKET, key=path)

def upload_avatar_image(user_file, user_profile, email):
    content_type = guess_type(user_file.name)[0]
    bucket_name = settings.S3_AVATAR_BUCKET
    s3_file_name = user_avatar_hash(email)
    upload_image_to_s3(
        bucket_name,
        s3_file_name,
        content_type,
        user_profile,
        user_file.read(),
    )
    # See avatar_url in avatar.py for URL.  (That code also handles the case
    # that users use gravatar.)

{'fraction_non_alphanumeric': 0.08629700446144041, 'fraction_numerical': 0.011982154238368388, 'mean_word_length': 3.5990621336459556, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5860825', 'n_tokens_mistral': 2619, 'n_tokens_neox': 2583, 'n_words': 588}