def test_unicode(self): from karl.views.utils import make_name context = {} self.assertEqual(make_name(context, u'what?'), "what") self.assertEqual(make_name(context, u"\u0fff"), "-fff-") self.assertEqual(make_name(context, u"\u0081\u0082"), "-81-82-") self.assertEqual(make_name(context, u'foo\u008ab\u00c3ll'), "foosball")
def __call__(self, v): if v in self.exceptions: return try: make_name(self.container, v) except ValueError, why: raise Invalid(why[0])
def test_make_name_without_error(self): from karl.views.utils import make_name context = testing.DummyModel() context['foo.bar'] = testing.DummyModel() try: self.assertEqual(make_name(context, "foo.bar"), 'foo.bar') except ValueError: pass else: self.fail("Expected a ValueError") self.assertEqual(make_name(context, "Test 1", raise_error=False), 'test-1')
def handle_submit(self, converted): request = self.request context = self.context workflow = self.workflow wikipage = create_content( IWikiPage, converted['title'], converted['text'], extract_description(converted['text']), authenticated_userid(request), ) name = make_name(context, converted['title']) context[name] = wikipage if workflow is not None: workflow.initialize(wikipage) if 'security_state' in converted: workflow.transition_to_state(wikipage, request, converted['security_state']) # Save the tags on it. set_tags(wikipage, request, converted['tags']) relocate_temp_images(wikipage, request) if converted['sendalert']: alerts = queryUtility(IAlerts, default=Alerts()) alerts.emit(wikipage, request) msg = '?status_message=Wiki%20Page%20created' location = resource_url(wikipage, request) + msg return HTTPFound(location=location)
def create(self, container): """ container is root['people']['categories'], or moral equivalent. """ title = self._element_value(self.element, 'title') sync_id = self.element.get('id') name = make_name(container, title) description = self._element_value(self.element, 'description') category_element = self.element.find(self.NS_PREFIX + 'category') category_id = category_element.get('id') category = container.get(category_id, None) if category is None: category = PeopleCategory(category_element.text.strip()) container[category_id] = category peopledir = find_peopledirectory(container) notify(PeopleDirectorySchemaChanged(peopledir)) category_item = PeopleCategoryItem(title, description) if sync_id is not None: category_item.sync_id = sync_id # OSI artifact if name in category: del category[name] category[name] = category_item
def handle_submit(self, converted): request = self.request context = self.context workflow = self.workflow wikipage = create_content( IWikiPage, converted['title'], converted['text'], extract_description(converted['text']), authenticated_userid(request), ) name = make_name(context, converted['title']) context[name] = wikipage if workflow is not None: workflow.initialize(wikipage) if 'security_state' in converted: workflow.transition_to_state(wikipage, request, converted['security_state']) # Save the tags on it. set_tags(wikipage, request, converted['tags']) relocate_temp_images(wikipage, request) if converted['sendalert']: alerts = queryUtility(IAlerts, default=Alerts()) alerts.emit(wikipage, request) msg = '?status_message=Wiki%20Page%20created' location = model_url(wikipage, request) + msg return HTTPFound(location=location)
def handle_submit(self, converted): request = self.request context = self.context name = make_name(context, converted['title']) userid = authenticated_userid(request) community = create_content( ICommunity, converted['title'], converted['description'], converted['text'], userid, ) community.sendalert_default = converted.get('sendalert_default', True) # this *must* directly follow content creation because the # toolinfo add stuff depends on the community having a full # path. context[name] = community # required to use moderators_group_name and # members_group_name community.__name__ = name tools_present = [] for toolinfo in self.available_tools: if toolinfo['name'] in converted.get('tools', []): toolinfo['component'].add(community, request) tools_present.append(toolinfo['name']) # Set the default tool if converted.get('default_tool') in tools_present: community.default_tool = converted['default_tool'] else: community.default_tool = None users = find_users(context) moderators_group_name = community.moderators_group_name members_group_name = community.members_group_name for group_name in moderators_group_name, members_group_name: users.add_group(userid, group_name) if self.workflow is not None: if 'security_state' in converted: self.workflow.transition_to_state(community, request, converted['security_state']) # Save the tags on it. set_tags(community, request, converted['tags']) # Adding a community should take you to the Add Existing # User screen, so the moderator can include some users. location = resource_url(community, request, 'members', 'add_existing.html', query={'status_message': 'Community added'}) return HTTPFound(location=location)
def handle_submit(self, converted): request = self.request context = self.context name = make_name(context, converted['title']) userid = authenticated_userid(request) community = create_content(ICommunity, converted['title'], converted['description'], converted['text'], userid, ) community.sendalert_default = converted.get('sendalert_default', True) # this *must* directly follow content creation because the # toolinfo add stuff depends on the community having a full # path. context[name] = community # required to use moderators_group_name and # members_group_name community.__name__ = name tools_present = [] for toolinfo in self.available_tools: if toolinfo['name'] in converted.get('tools', []): toolinfo['component'].add(community, request) tools_present.append(toolinfo['name']) # Set the default tool if converted.get('default_tool') in tools_present: community.default_tool = converted['default_tool'] else: community.default_tool = None users = find_users(context) moderators_group_name = community.moderators_group_name members_group_name = community.members_group_name for group_name in moderators_group_name, members_group_name: users.add_group(userid, group_name) if self.workflow is not None: if 'security_state' in converted: self.workflow.transition_to_state(community, request, converted['security_state']) # Save the tags on it. set_tags(community, request, converted['tags']) # Adding a community should take you to the Add Existing # User screen, so the moderator can include some users. location = resource_url( community, request, 'members', 'add_existing.html', query={'status_message': 'Community added'}) return HTTPFound(location=location)
def menu_item(title, url, id=None, count=None, secondary=None): if id is None: id = make_name(EMPTY_CONTEXT, title) selected = request.url.startswith(url) if secondary is not None and not selected: selected = request.url.startswith(secondary) item = dict(title=title, url=url, id=id, selected=selected and 'selected' or None) if count is not None: item['count'] = count return item
def menu_item(title, url, id=None, count=None, secondary=None): if id is None: id = make_name(EMPTY_CONTEXT, title) selected = request.resource_url(context).startswith(url) if secondary is not None and not selected: selected = request.resource_url(context).startswith(secondary) item = dict(title=title, url=url, id=id, selected=selected and 'selected' or None) if count is not None: item['count'] = count return item
def handle_submit(self, converted): request = self.request context = self.context workflow = self.workflow creator = authenticated_userid(request) f = converted['file'] if not f.file: raise ValidationError(file='Must upload a file') file = create_content(ICommunityFile, title=converted['title'], stream=f.file, mimetype=get_mimetype(f.mimetype, f.filename), filename=f.filename, creator=creator, ) self.check_upload_size(context, file, 'file') # 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(f.filename) file.filename = filename name = make_name(context, filename, raise_error=False) if not name: msg = 'The filename must not be empty' raise ValidationError(file=msg) # Is there a key in context with that filename? if name in context: msg = 'Filename %s already exists in this folder' % filename raise ValidationError(file=msg) context[name] = file if workflow is not None: workflow.initialize(file) if 'security_state' in converted: workflow.transition_to_state(file, request, converted['security_state']) # Tags, attachments, alerts set_tags(file, request, converted['tags']) if converted.get('sendalert'): alerts = queryUtility(IAlerts, default=Alerts()) alerts.emit(file, request) self.filestore.clear() location = model_url(file, request) return HTTPFound(location=location)
def test_make_name(self): from karl.views.utils import make_name context = {} self.assertEqual(make_name(context, "foo.bar"), "foo.bar") self.assertEqual(make_name(context, "Harry 'Bigfoot' Henderson"), "harry-bigfoot-henderson") self.assertEqual(make_name(context, "Which one?"), "which-one") self.assertEqual(make_name(context, "One/Two/Three"), "one-two-three") self.assertEqual(make_name(context, "Genesis 1:1"), "genesis-1-1") self.assertEqual(make_name(context, "'My Life'"), "-my-life-")
def handle_submit(self, converted): request = self.request context = self.context intranets_parent = find_community(context) name = converted.get('name') if name: name_from = 'name' else: name = converted['title'] name_from = 'title' try: name = make_name(intranets_parent, name) except ValueError, why: msg = why[0] raise ValidationError(**{name_from: msg})
def relocate(match): matchdict = match.groupdict() tempid = matchdict['tempid'] if tempid in relocated_images: # Already relocated this one url = relocated_images[tempid] else: # Move temp image to attachments folder image = tempfolder[tempid] del tempfolder[tempid] name = make_name(attachments, image.filename) attachments[name] = image size = (int(matchdict['width']), int(matchdict['height'])) url = thumb_url(image, request, size) relocated_images[tempid] = url return ''.join([matchdict['pre'], url, matchdict['post'],])
def create(self, container): """ container is root['people'].categories, or moral equivalent. """ title = _element_value(self, self.element, 'title') sync_id = self.element.get('id') name = make_name(container, title) description = _element_value(self, self.element, 'description') category_element = self.element.find(self.NS_PREFIX + 'category') category_id = category_element.get('id') category = container.get(category_id, None) if category is None: category = PeopleCategory(category_element.text.strip()) container[category_id] = category peopledir = find_peopledirectory(container) notify(PeopleDirectorySchemaChanged(peopledir)) category_item = PeopleCategoryItem(title, description) if sync_id is not None: category_item.sync_id = sync_id # OSI artifact category[name] = category_item
def _fix_link_traverser(context, traversed, subpath): if not subpath: # We're done, return traversed path return '/' + '/'.join(traversed) next = subpath.pop(0) # Easy case, normal traversal if hasattr(context, '__getitem__') and next in context: traversed.append(next) return _fix_link_traverser(context[next], traversed, subpath) # Karl2 site was actually rooted at /Plone/public # Although you wouldn't normally include that in a link url, # because of acquisition you could! # If we find this or some variation at the beginning of a link # just try to skip it. skippable = ( 'Plone', 'public', ) if not traversed and next in skippable: return _fix_link_traverser(context, traversed, subpath) # An 'index_html' at the end is not necessary and skippable. # Some links inexplicably end with a '/&', which is also # skippable. skippable2 = ( 'index_html', '&', ) if next in skippable2: return _fix_link_traverser(context, traversed, subpath) # Can't find next element. Maybe it is a view if _check_view(context, next): # We can stop here, traversed path with view traversed.append(next) return '/' + '/'.join(traversed + subpath) # In Karl2 there was a content type for images that used a view # In Karl3, these are just files, so where we might have had a # view named 'image' in Karl2, we just have the 'dl' view in Karl3 if next == 'image' and _check_view(context, 'dl'): # Got the view, we can stop here traversed.append('dl') return '/' + '/'.join(traversed + subpath) # Maybe next was resolved via acquisition in Karl2 aq_context = _acquire(context, next) if aq_context: # Rewrite the leading part of this path as the model_path of the # acquired context. aq_path = model_path(aq_context) log.debug("Acquisition: rewrote path: %s -> %s", traversed, aq_path) traversed = aq_path[1:].split('/') return _fix_link_traverser(aq_context, traversed, subpath) # Next may have been processed through make_name in Karl3. Try # processing the name and see if that finds the next element. if hasattr(context, '__getitem__'): # This fix only makes sense if current node is traversable try: name = make_name({}, urllib.unquote(next)) if name in context: traversed.append(name) return _fix_link_traverser(context[name], traversed, subpath) except ValueError: # make_name will throw ValueError if there are no alphanumerics # in next pass # Some links in Karl2 are to /profile/<user> rather than # /profiles/<user>. Try changing profile to profiles and # see if that fixes the problem. if next == 'profile': subpath.insert(0, 'profiles') return _fix_link_traverser(context, traversed, subpath) # Links to /osipeople_*.html can be rewritten as just /people if next.startswith('osipeople_') and next.endswith('.html'): subpath.insert(0, 'people') return _fix_link_traverser(context, traversed, subpath) # There are some links to just /network-news and /network-events. # These are located in /offices/files if next in ('network-news', 'network-events'): subpath.insert(0, next) subpath.insert(0, 'files') subpath.insert(0, 'offices') return _fix_link_traverser(context, traversed, subpath) # Out of tricks, give up log.debug("Couldn't fix") log.debug("Traversed: %s", traversed) log.debug("Not found: %s", next) return None
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) stream = fieldstorage.file title = fieldstorage.filename image = create_content(ICommunityFile, title=title, stream=stream, mimetype=get_upload_mimetype(fieldstorage), filename=fieldstorage.filename, creator=creator, ) 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) # 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) 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 else: tempfolder = find_tempfolder(context) tempfolder.add_document(image) workflow = get_workflow(ICommunityFile, 'security', context) if workflow is not None: workflow.initialize(image) # Update the thumbnails return dict( upload_image_info=get_image_info(image, request), images_info=batch_images(context, request), )
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), )