Exemplo n.º 1
0
def thumb_url(image, request, size):
    """
    Return the url for displaying the image with dimensions bounded by given
    size.
    """
    assert IImage.providedBy(image), "Cannot take thumbnail of non-image."
    return resource_url(image, request, 'thumb', '%dx%d.jpg' % size)
Exemplo n.º 2
0
def thumb_url(image, request, size):
    """
    Return the url for displaying the image with dimensions bounded by given
    size.
    """
    assert IImage.providedBy(image), "Cannot take thumbnail of non-image."
    return model_url(image, request, 'thumb', '%dx%d.jpg' % size)
Exemplo n.º 3
0
def thumbnail_view(context, request):
    assert IImage.providedBy(context), "Context must be an image."
    filename = request.subpath[0] # <width>x<length>.jpg
    size = map(int, filename[:-4].split('x'))
    thumb = context.thumbnail(tuple(size))

    # XXX Allow browser caching be setting Last-modified and Expires
    #     and respecting If-Modified-Since requests with 302 responses.
    data = thumb.blobfile.open().read()
    return Response(body=data, content_type=thumb.mimetype)
Exemplo n.º 4
0
def thumb_url(image, request, size):
    """
    Return the url for displaying the image with dimensions bounded by given
    size.
    """
    from karl.views.api import TemplateAPI # avoid circref
    if not IImage.providedBy(image):
        api = TemplateAPI(image, request, '')
        return api.static_url + "/images/brokenImage.gif"
    return resource_url(image, request, 'thumb', '%dx%d.jpg' % size)
Exemplo n.º 5
0
def thumb_url(image, request, size):
    """
    Return the url for displaying the image with dimensions bounded by given
    size.
    """
    from karl.views.api import TemplateAPI  # avoid circref
    if not IImage.providedBy(image):
        api = TemplateAPI(image, request, '')
        return api.static_url + "/images/brokenImage.gif"
    return resource_url(image, request, 'thumb', '%dx%d.jpg' % size)
Exemplo n.º 6
0
    def test_jpg(self):
        from karl.content.interfaces import IImage
        from pkg_resources import resource_stream
        stream = resource_stream('karl.content.models.tests', 'test.jpg')
        o = self._makeOne(stream=stream, mimetype='image/jpeg')
        self.failUnless(o.is_image)
        self.failUnless(IImage.providedBy(o))
        self.assertEqual(o.image_size, (390, 569))
        self.assertEqual(o.image().size, (390, 569))

        from zope.interface.verify import verifyObject
        verifyObject(IImage, o)
Exemplo n.º 7
0
    def test_instance_has_valid_construction(self):
        instance = self._makeOne()
        self.assertEqual(instance.title, u'title')
        self.assertEqual(instance.creator, u'admin')
        self.assertEqual(instance.modified_by, u'admin')
        self.assertEqual(instance.blobfile.open().read(), 'FAKECONTENT')
        self.assertEqual(instance.size, 11)
        self.assertEqual(instance.mimetype, 'text/plain')
        self.assertEqual(instance.filename, 'afile.txt')
        self.failIf(instance.is_image)

        from karl.content.interfaces import IImage
        self.failIf(IImage.providedBy(instance))
Exemplo n.º 8
0
    def test_jpg(self):
        from karl.content.interfaces import IImage
        from pkg_resources import resource_stream
        stream = resource_stream('karl.content.models.tests', 'test.jpg')
        o = self._makeOne(stream=stream, mimetype='image/jpeg')
        self.failUnless(o.is_image)
        self.failUnless(IImage.providedBy(o))
        self.assertEqual(o.image_size, (390, 569))
        self.assertEqual(o.image().size, (390, 569))

        from zope.interface.verify import verifyObject
        verifyObject(IImage, o)
        return o
Exemplo n.º 9
0
    def test_instance_has_valid_construction(self):
        instance = self._makeOne()
        self.assertEqual(instance.title, u'title')
        self.assertEqual(instance.creator, u'admin')
        self.assertEqual(instance.modified_by, u'admin')
        self.assertEqual(instance.blobfile.open().read(), 'FAKECONTENT')
        self.assertEqual(instance.size, 11)
        self.assertEqual(instance.mimetype, 'text/plain')
        self.assertEqual(instance.filename, 'afile.txt')
        self.failIf(instance.is_image)

        from karl.content.interfaces import IImage
        self.failIf(IImage.providedBy(instance))
Exemplo n.º 10
0
def vocabulary_view(context, request):
    try:
        attributes = json.loads(request.params.get('attributes', '["title", "id"]'))
    except:
        attributes = ['title', 'id']
    if 'UID' in attributes:
        # always put in anyways
        attributes.remove('UID')

    try:
        batch = json.loads(request.params.get('batch'))
    except:
        batch = DEFAULT_BATCH

    query = normalize_query(json.loads(request.params['query']))
    criteria = parse_query(query)

    resolver = ResovlerFactory(context)
    if 'UID' in query:
        docids = query['UID']
        if type(docids) not in (list, tuple):
            docids = [docids]
        # convert to ints
        new_docids = []
        for docid in docids:
            try:
                new_docids.append(int(docid))
            except:
                pass
        docids = new_docids
        numdocs = len(docids)
    else:
        criteria.append(Any('allowed', effective_principals(request)))
        if 'title' not in query:
            # we default to requiring a title in these results or
            # else we get a bunch of junky results
            criteria.append(NotEq('title', ''))
        catalog = find_catalog(context)
        numdocs, docids = catalog.query(And(*criteria))

    if batch and ('size' not in batch or 'page' not in batch):
        batch = DEFAULT_BATCH
    if batch:
        # must be slicable for batching support
        page = int(batch['page'])
        # page is being passed in is 1-based
        start = (max(page - 1, 0)) * int(batch['size'])
        end = start + int(batch['size'])
        # Try __getitem__-based slice, then iterator slice.
        # The iterator slice has to consume the iterator through
        # to the desired slice, but that shouldn't be the end
        # of the world because at some point the user will hopefully
        # give up scrolling and search instead.
        try:
            docids = docids[start:end]
        except TypeError:
            docids = itertools.islice(docids, start, end)

    # build result items
    items = []
    for docid in docids:
        result = resolver(docid)
        if result is None:
            continue
        data = {
            'UID': docid
        }
        for attribute in attributes:
            attr = attribute
            if attribute in _attribute_mapping:
                attr = _attribute_mapping[attribute]
            if attr in ('Type', 'portal_type'):
                value = 'Page'
                if IImage.providedBy(result):
                    value = 'Image'
                elif ICommunityFile.providedBy(result):
                    value = 'File'
                elif IFolder.providedBy(result):
                    value = 'Folder'
            elif attr == 'getURL':
                value = resource_url(result, request)
            elif attr == 'path':
                # a bit weird here...
                value = resource_path(result, request).split('/GET')[0]
            else:
                value = getattr(result, attr, None)
            data[attribute] = value
        items.append(data)
    return {
        'results': items,
        'total': numdocs
    }
Exemplo n.º 11
0
def drawer_upload_view(context, request,
                       check_upload_size=check_upload_size,
                       get_image_info=get_image_info,
                       batch_images=batch_images,
                       ):
    """Drawer posts a file with the parameter name "file".
    """

    ## XXX The rest is copied from add_file_view. A common denominator
    ## would be desirable.

    creator = authenticated_userid(request)

    fieldstorage = request.params.get('file')
    if not hasattr(fieldstorage, 'filename'):
        msg = 'You must select a file before clicking Upload.'
        return dict(error = msg)

    # For file objects, OSI's policy is to store the upload file's
    # filename as the objectid, instead of basing __name__ on the
    # title field).
    filename = basename_of_filepath(fieldstorage.filename)

    stream = fieldstorage.file
    # use parameter, as the title (or basename, if missing).
    title = request.params.get('title', filename)
    image = create_content(ICommunityFile,
                          title=title,
                          stream=stream,
                          mimetype=get_upload_mimetype(fieldstorage),
                          filename=fieldstorage.filename,
                          creator=creator,
                          )
    # Check if it's an image.
    if not IImage.providedBy(image):
        msg = 'File %s is not an image' % filename
        return dict(error=msg)

    check_upload_size(context, image, 'file')

    if hasattr(context, 'get_attachments'):
        target_folder = context.get_attachments()
        if not has_permission('create', target_folder, request):
            msg = 'You do not have permission to upload files here.'
            return dict(error=msg)

        image.filename = filename
        name = make_name(target_folder, filename, raise_error=False)
        if not name:
            msg = 'The filename must not be empty'
            return dict(error=msg)

        # Is there a key in context with that filename?
        if name in target_folder:
            msg = 'Filename %s already exists in this folder' % filename
            return dict(error=msg)

        target_folder[name] = image

        workflow = get_workflow(ICommunityFile, 'security', context)
        if workflow is not None:
            workflow.initialize(image)

    # In cases where the image is to live in a piece of content which has not
    # yet been created (like when using an 'Add' form), the context is going
    # to be the eventual parent of the not yet created content, which will be
    # the eventual parent of the just now created image.  Since we have nowhere
    # to put the image, we put it in a tempfolder and later move it over after
    # the content is created.  Normal ContentAdded event handlers are not
    # called at this stage and workflow is not yet initialized.  These will
    # occur when the content is moved over.
    else:
        image.modified = datetime.datetime.now()
        tempfolder = find_tempfolder(context)
        tempfolder.add_document(image)


    # Return info about the image uploaded
    return dict(
        upload_image_info=get_image_info(image, request, thumb_size=LARGE_THUMB_SIZE),
    )
Exemplo n.º 12
0
def batch_images(context, request,
                 get_image_info=get_image_info, # unittest
                 get_images_batch=get_images_batch): # unittest

    include_image_url = request.params.get('include_image_url', None)
    # include_image_url is a special case.
    include_info = None
    if include_image_url is not None:
        # Note, we must use the path only, as IE submits the full domain
        # and without the next line IE would fail.
        path = urlparse.urlparse(include_image_url)[2]
        include_context = traverse(context, path)['context']
        if IImage.providedBy(include_context):
            # We have a good image to include.
            include_info = get_image_info(include_context, request)

    # Find query parameters based on the 'source' param,
    # which signifies the selection index of the source button
    # in the imagedrawer dialog.
    source = request.params.get('source')
    assert source in ('myrecent', 'thiscommunity', 'allkarl')

    if source == 'myrecent':
        creator = authenticated_userid(request)
        community_path = None
    elif source == 'thiscommunity':
        creator = None
        community = find_community(context)
        # batching api requires the community path
        community_path = resource_path(community)
    else:               # All Karl
        creator = None
        community_path = None

    # batching
    # Decide start and size here, don't let the lower levels
    # apply their default. This allows us to enforce
    # a MINIMAL_BATCH size.
    batch_start = int(request.params.get('start', '0'))
    batch_size = int(request.params.get('limit', '0'))
    # there is a minimal batch size to enforce, if the client
    # does not ask for one
    # Just pass the values to lower levels where sensible
    # defaults will be applied.
    sort_index = request.params.get('sort_on', None)
    reverse = request.params.get('reverse', None)

    # XXX include_image will now be inserted in the first
    # position, as extra image.
    insert_extra = False
    if include_info is not None:
        if batch_start == 0:
            batch_size -= 1
            insert_extra = True
        else:
            batch_start -= 1

    # Enforce the minimal batch size
    batch_size = max(batch_size, MINIMAL_BATCH)

    search_params = dict(
        creator=creator,
        community=community_path,
        batch_start=batch_start,
        batch_size=batch_size,
    )
    if sort_index:
        search_params['sort_index'] = sort_index
    if reverse:
        search_params['reverse'] = bool(int(reverse))

    batch_info = get_images_batch(
        context,
        request,
        **search_params
    )

    records = [get_image_info(image, request)
               for image in batch_info['entries']]
    start = batch_info['batch_start']
    totalRecords = batch_info['total']

    # add the fake included image
    if include_info is not None:
        totalRecords += 1
        if insert_extra:
            records.insert(0, include_info)
        else:
            start += 1

    return dict(
        records = records,
        start = start,
        totalRecords = totalRecords,
        )
Exemplo n.º 13
0
def drawer_upload_view(context, request,
                       check_upload_size=check_upload_size,
                       get_image_info=get_image_info,
                       batch_images=batch_images,
                       ):
    """Drawer posts a file with the parameter name "file".
    """

    ## XXX The rest is copied from add_file_view. A common denominator
    ## would be desirable.

    creator = authenticated_userid(request)

    fieldstorage = request.params.get('file')
    if not hasattr(fieldstorage, 'filename'):
        msg = 'You must select a file before clicking Upload.'
        return dict(error = msg)

    # For file objects, OSI's policy is to store the upload file's
    # filename as the objectid, instead of basing __name__ on the
    # title field).
    filename = basename_of_filepath(fieldstorage.filename)

    stream = fieldstorage.file
    # use parameter, as the title (or basename, if missing).
    title = request.params.get('title', filename)
    image = create_content(ICommunityFile,
                          title=title,
                          stream=stream,
                          mimetype=get_upload_mimetype(fieldstorage),
                          filename=fieldstorage.filename,
                          creator=creator,
                          )
    # Check if it's an image.
    if not IImage.providedBy(image):
        msg = 'File %s is not an image' % filename
        return dict(error=msg)

    check_upload_size(context, image, 'file')

    if hasattr(context, 'get_attachments'):
        target_folder = context.get_attachments()
        if not has_permission('create', target_folder, request):
            msg = 'You do not have permission to upload files here.'
            return dict(error=msg)

        image.filename = filename
        name = make_name(target_folder, filename, raise_error=False)
        if not name:
            msg = 'The filename must not be empty'
            return dict(error=msg)

        # Is there a key in context with that filename?
        if name in target_folder:
            msg = 'Filename %s already exists in this folder' % filename
            return dict(error=msg)

        target_folder[name] = image

        workflow = get_workflow(ICommunityFile, 'security', context)
        if workflow is not None:
            workflow.initialize(image)

    # In cases where the image is to live in a piece of content which has not
    # yet been created (like when using an 'Add' form), the context is going
    # to be the eventual parent of the not yet created content, which will be
    # the eventual parent of the just now created image.  Since we have nowhere
    # to put the image, we put it in a tempfolder and later move it over after
    # the content is created.  Normal ContentAdded event handlers are not
    # called at this stage and workflow is not yet initialized.  These will
    # occur when the content is moved over.
    else:
        image.modified = datetime.datetime.now()
        tempfolder = find_tempfolder(context)
        tempfolder.add_document(image)


    # Return info about the image uploaded
    return dict(
        upload_image_info=get_image_info(image, request, thumb_size=LARGE_THUMB_SIZE),
    )
Exemplo n.º 14
0
def batch_images(context, request,
                 get_image_info=get_image_info, # unittest
                 get_images_batch=get_images_batch): # unittest

    include_image_url = request.params.get('include_image_url', None)
    # include_image_url is a special case.
    include_info = None
    if include_image_url is not None:
        # Note, we must use the path only, as IE submits the full domain
        # and without the next line IE would fail.
        path = urlparse.urlparse(include_image_url)[2]
        include_context = traverse(context, path)['context']
        if IImage.providedBy(include_context):
            # We have a good image to include.
            include_info = get_image_info(include_context, request)

    # Find query parameters based on the 'source' param,
    # which signifies the selection index of the source button
    # in the imagedrawer dialog.
    source = request.params.get('source')
    assert source in ('myrecent', 'thiscommunity', 'allkarl')

    if source == 'myrecent':
        creator = authenticated_userid(request)
        community_path = None
    elif source == 'thiscommunity':
        creator = None
        community = find_community(context)
        # batching api requires the community path
        community_path = resource_path(community)
    else:               # All Karl
        creator = None
        community_path = None

    # batching
    # Decide start and size here, don't let the lower levels
    # apply their default. This allows us to enforce
    # a MINIMAL_BATCH size.
    batch_start = int(request.params.get('start', '0'))
    batch_size = int(request.params.get('limit', '0'))
    # there is a minimal batch size to enforce, if the client
    # does not ask for one
    # Just pass the values to lower levels where sensible
    # defaults will be applied.
    sort_index = request.params.get('sort_on', None)
    reverse = request.params.get('reverse', None)

    # XXX include_image will now be inserted in the first
    # position, as extra image.
    insert_extra = False
    if include_info is not None:
        if batch_start == 0:
            batch_size -= 1
            insert_extra = True
        else:
            batch_start -= 1

    # Enforce the minimal batch size
    batch_size = max(batch_size, MINIMAL_BATCH)

    search_params = dict(
        creator=creator,
        community=community_path,
        batch_start=batch_start,
        batch_size=batch_size,
    )
    if sort_index:
        search_params['sort_index'] = sort_index
    if reverse:
        search_params['reverse'] = bool(int(reverse))

    batch_info = get_images_batch(
        context,
        request,
        **search_params
    )

    records = [get_image_info(image, request)
               for image in batch_info['entries']]
    start = batch_info['batch_start']
    totalRecords = batch_info['total']

    # add the fake included image
    if include_info is not None:
        totalRecords += 1
        if insert_extra:
            records.insert(0, include_info)
        else:
            start += 1

    return dict(
        records = records,
        start = start,
        totalRecords = totalRecords,
        )