示例#1
0
文件: feed.py 项目: rockyburt/Rezine
class FeedImporter(Importer):
    name = 'feed'
    title = lazy_gettext(u'Feed Importer')
    description = lazy_gettext(u'Handles ATOM feeds with optional extensions '
                               u'such as those exported by Rezine itself. '
                               u'Plugins can add further extensions to be '
                               u'recognized by this importer.')

    def configure(self, request):
        form = FeedImportForm()

        if request.method == 'POST' and form.validate(request.form):
            feed = request.files.get('feed')
            if form.data['download_url']:
                try:
                    feed = open_url(form.data['download_url']).stream
                except Exception, e:
                    log.exception(_('Error downloading feed'))
                    flash(_(u'Error downloading from URL: %s') % e, 'error')
            if not feed:
                return redirect_to('import/feed')

            try:
                blog = parse_feed(feed)
            except Exception, e:
                log.exception(_(u'Error parsing uploaded file'))
                flash(_(u'Error parsing feed: %s') % e, 'error')
            else:
示例#2
0
class WordPressImporter(Importer):
    name = 'wordpress'
    title = 'WordPress'
    description = lazy_gettext(u'Handles import of WordPress "extended RSS" '
                               u' feeds.')

    def configure(self, request):
        form = WordPressImportForm()

        if request.method == 'POST' and form.validate(request.form):
            dump = request.files.get('dump')
            if form.data['download_url']:
                try:
                    dump = open_url(form.data['download_url']).stream
                except Exception, e:
                    log.exception(_('Error downloading feed'))
                    flash(_(u'Error downloading from URL: %s') % e, 'error')
            if not dump:
                return redirect_to('import/wordpress')

            try:
                blog = parse_feed(dump)
            except Exception, e:
                raise
                log.exception(_(u'Error parsing uploaded file'))
                flash(_(u'Error parsing uploaded file: %s') % e, 'error')
            else:
示例#3
0
class PlainTextParser(BaseParser):
    """Parses simple text into a ZEML tree by utilizing pottymouth."""

    name = lazy_gettext('Text')

    def _to_text(self, token):
        """Convert a token to normal text."""
        return replace_entities(unicode(token))

    def _to_zeml(self, node, untrusted=False):
        """Convert a potty-mouth node into a ZEML tree."""
        from rezine._ext.pottymouth import Token
        def add_text(node, text):
            if node.children:
                node.children[-1].tail += text
            else:
                node.text += text

        def convert(node, is_root):
            if is_root:
                result = RootElement()
            else:
                result = Element(node.name)
            if node._attributes:
                result.attributes.update(node._attributes)

            for item in node:
                if isinstance(item, (str, unicode, Token)):
                    add_text(result, self._to_text(item))
                else:
                    child = convert(item, False)
                    # remove the useless empty spans
                    if child.name == 'span' and not child.attributes:
                        add_text(result, child.text)
                        result.children.extend(child.children)
                        add_text(result, child.tail)
                    else:
                        result.children.append(child)

            # fixes an output bug from pottymouth
            if len(result.children) == 1 and node.name == 'p' and \
               result.children[0].name == 'blockquote':
                result = result.children[0]

            # untrusted posts get nofollow on links
            if untrusted and result.name == 'a':
                result.attributes['rel'] = 'nofollow'

            return result
        return convert(node, True)

    def parse(self, input_data, reason):
        from rezine._ext.pottymouth import PottyMouth
        parser = PottyMouth(emdash=False, ellipsis=False, smart_quotes=False,
                            youtube=False, image=False, italic=False,
                            all_links=not self.app.cfg['plaintext_parser_nolinks'])
        node = parser.parse(input_data)
        return self._to_zeml(node, reason == 'comment')
示例#4
0
class ZEMLParser(BaseParser):
    """The parser for the ZEML Markup language."""

    name = lazy_gettext('Rezine-Markup')

    def parse(self, input_data, reason):
        rv = parse_zeml(input_data, reason, self.app.markup_extensions)
        if reason == 'comment':
            rv = sanitize(rv)
        return rv
示例#5
0
class HTMLParser(BaseParser):
    """A parser that understands plain old HTML."""

    name = lazy_gettext('HTML')

    def parse(self, input_data, reason):
        rv = parse_html(input_data)
        if reason == 'comment':
            rv = sanitize(rv)
        return rv
示例#6
0
class InstallationError(UserException):
    """Raised during plugin installation."""

    MESSAGES = {
        'invalid':
        lazy_gettext('Could not install the plugin because the '
                     'uploaded file is not a valid plugin file.'),
        'version':
        lazy_gettext('The plugin uploaded has a newer package '
                     'version than this Rezine installation '
                     'can handle.'),
        'exists':
        lazy_gettext('A plugin with the same UID is already '
                     'installed. Aborted.'),
        'ioerror':
        lazy_gettext('Could not install the package because the '
                     'installer wasn\'t able to write the package '
                     'information. Wrong permissions?')
    }

    def __init__(self, code):
        UserException.__init__(self, self.MESSAGES[code])
        self.code = code
示例#7
0
def is_valid_url(message=None):
    """Check if the string passed is a valid URL.  We also blacklist some
    url schemes like javascript for security reasons.

    >>> check(is_valid_url, 'http://pocoo.org/')
    True
    >>> check(is_valid_url, 'http://rezine.pocoo.org/archive')
    True
    >>> check(is_valid_url, 'rezine.pocoo.org/archive')
    False
    >>> check(is_valid_url, 'javascript:alert("Rezine rocks!");')
    False
    """
    if message is None:
        message = lazy_gettext(u'You have to enter a valid URL.')
    def validator(form, value):
        protocol = urlparse(value)[0]
        if not protocol or protocol == 'javascript':
            raise ValidationError(message)
    return validator
示例#8
0
def is_valid_email(message=None):
    """Check if the string passed is a valid mail address.

    >>> check(is_valid_email, '*****@*****.**')
    True
    >>> check(is_valid_email, 'somebody AT example DOT com')
    False
    >>> check(is_valid_email, 'some random string')
    False

    Because e-mail validation is painfully complex we just check the first
    part of the email if it looks okay (comments are not handled!) and ignore
    the second.
    """
    if message is None:
        message = lazy_gettext(u'You have to enter a valid e-mail address.')
    def validator(form, value):
        if len(value) > 250 or _mail_re.match(value) is None:
            raise ValidationError(message)
    return validator
示例#9
0
class ConfigurationTransactionError(InternalError):
    """An exception that is raised if the transaction was unable to
    write the changes to the config file.
    """

    help_text = lazy_gettext(u'''
    <p>
      This error can happen if the configuration file is not writeable.
      Make sure the folder of the configuration file is writeable and
      that the file itself is writeable as well.
    ''')

    def __init__(self, message_or_exception):
        if isinstance(message_or_exception, basestring):
            message = message_or_exception
            error = None
        else:
            message = _(u'Could not save configuration file: %s') % \
                      str(message_or_exception).decode('utf-8', 'ignore')
            error = message_or_exception
        InternalError.__init__(self, message)
        self.original_exception = error
示例#10
0
def is_valid_url(message=None):
    """Check if the string passed is a valid URL.  We also blacklist some
    url schemes like javascript for security reasons.

    >>> check(is_valid_url, 'http://pocoo.org/')
    True
    >>> check(is_valid_url, 'http://rezine.pocoo.org/archive')
    True
    >>> check(is_valid_url, 'rezine.pocoo.org/archive')
    False
    >>> check(is_valid_url, 'javascript:alert("Rezine rocks!");')
    False
    """
    if message is None:
        message = lazy_gettext(u'You have to enter a valid URL.')

    def validator(form, value):
        protocol = urlparse(value)[0]
        if not protocol or protocol == 'javascript':
            raise ValidationError(message)

    return validator
示例#11
0
def is_valid_email(message=None):
    """Check if the string passed is a valid mail address.

    >>> check(is_valid_email, '*****@*****.**')
    True
    >>> check(is_valid_email, 'somebody AT example DOT com')
    False
    >>> check(is_valid_email, 'some random string')
    False

    Because e-mail validation is painfully complex we just check the first
    part of the email if it looks okay (comments are not handled!) and ignore
    the second.
    """
    if message is None:
        message = lazy_gettext(u'You have to enter a valid e-mail address.')

    def validator(form, value):
        if len(value) > 250 or _mail_re.match(value) is None:
            raise ValidationError(message)

    return validator
示例#12
0
            user = get_request().user
        for notification in self.notification_types.itervalues():
            if user.has_privilege(notification.privileges):
                yield notification

    def add_notification_type(self, notification):
        self.notification_types[type.name] = type


def _register(name, description, privileges=ENTER_ACCOUNT_PANEL):
    """Register a new builtin type of notifications."""
    nottype = NotificationType(name, description, privileges)
    DEFAULT_NOTIFICATION_TYPES[name] = nottype
    globals()[name] = nottype
    __all__.append(name)


_register('NEW_COMMENT',
          lazy_gettext(u'When a new comment is received.'))
_register('COMMENT_REQUIRES_MODERATION',
          lazy_gettext(u'When a comment requires moderation.'),
          (MODERATE_OWN_PAGES | MODERATE_OWN_ENTRIES | MODERATE_COMMENTS))
_register('SECURITY_ALERT',
          lazy_gettext(u'When Rezine found an urgent security alarm.'),
          BLOG_ADMIN)
_register('ZINE_ERROR', lazy_gettext(u'When Rezine throws errors.'), BLOG_ADMIN)


DEFAULT_NOTIFICATION_SYSTEMS = [EMailNotificationSystem]
del _register
示例#13
0
class EMailNotificationSystem(NotificationSystem):
    """Sends notifications to user via E-Mail."""

    key = 'email'
    name = lazy_gettext(u'E-Mail')

    def send(self, user, notification):
        title = u'[%s] %s' % (self.app.cfg['blog_title'],
                              notification.title.to_text())
        text = self.mail_from_notification(notification)
        send_email(title, text, [user.email])

    def unquote_link(self, link):
        """Unquotes some kinds of links.  For example mailto:foo links are
        stripped and properly unquoted because the mails we write are in
        plain text and nobody is interested in URLs there.
        """
        scheme, netloc, path = urlsplit(link)[:3]
        if scheme == 'mailto':
            return url_unquote(path)
        return link

    def collect_list_details(self, container):
        """Returns the information collected from a single detail list item."""
        for item in container.children:
            if len(item.children) == 1 and item.children[0].name == 'a':
                link = item.children[0]
                href = link.attributes.get('href')
                yield dict(text=link.to_text(simple=True),
                           link=self.unquote_link(href),
                           is_textual=False)
            else:
                yield dict(text=item.to_text(multiline=False),
                           link=None,
                           is_textual=True)

    def find_details(self, container):
        # no container given, nothing can be found
        if container is None or not container.children:
            return []

        result = []
        for child in container.children:
            if child.name in ('ul', 'ol'):
                result.extend(self.collect_list_details(child))
            elif child.name == 'p':
                result.extend(
                    dict(text=child.to_text(), link=None, is_textual=True))
        return result

    def find_actions(self, container):
        if not container:
            return []
        ul = container.query('/ul').first
        if not ul:
            return []
        return list(self.collect_list_details(ul))

    def mail_from_notification(self, message):
        title = message.title.to_text()
        details = self.find_details(message.details)
        longtext = message.longtext.to_text(collect_urls=True,
                                            initial_indent=2)
        actions = self.find_actions(message.actions)
        return render_template('notifications/email.txt',
                               title=title,
                               details=details,
                               longtext=longtext,
                               actions=actions)
示例#14
0
        if not user:
            user = get_request().user
        for notification in self.notification_types.itervalues():
            if user.has_privilege(notification.privileges):
                yield notification

    def add_notification_type(self, notification):
        self.notification_types[type.name] = type


def _register(name, description, privileges=ENTER_ACCOUNT_PANEL):
    """Register a new builtin type of notifications."""
    nottype = NotificationType(name, description, privileges)
    DEFAULT_NOTIFICATION_TYPES[name] = nottype
    globals()[name] = nottype
    __all__.append(name)


_register('NEW_COMMENT', lazy_gettext(u'When a new comment is received.'))
_register('COMMENT_REQUIRES_MODERATION',
          lazy_gettext(u'When a comment requires moderation.'),
          (MODERATE_OWN_PAGES | MODERATE_OWN_ENTRIES | MODERATE_COMMENTS))
_register('SECURITY_ALERT',
          lazy_gettext(u'When Rezine found an urgent security alarm.'),
          BLOG_ADMIN)
_register('ZINE_ERROR', lazy_gettext(u'When Rezine throws errors.'),
          BLOG_ADMIN)

DEFAULT_NOTIFICATION_SYSTEMS = [EMailNotificationSystem]
del _register
示例#15
0
        return priv

    return db.association_proxy(lowlevel_attribute,
                                'privilege',
                                creator=creator_func)


def _register(name, description, privilege_dependencies=None):
    """Register a new builtin privilege."""
    priv = Privilege(name, description, privilege_dependencies)
    DEFAULT_PRIVILEGES[name] = priv
    globals()[name] = priv
    __all__.append(name)


_register('ENTER_ADMIN_PANEL', lazy_gettext(u'can enter admin panel'))
_register('BLOG_ADMIN', lazy_gettext(u'can administer the blog'))
_register('CREATE_ENTRIES', lazy_gettext(u'can create new entries'),
          ENTER_ADMIN_PANEL)
_register('EDIT_OWN_ENTRIES', lazy_gettext(u'can edit their own entries'),
          (ENTER_ADMIN_PANEL | CREATE_ENTRIES))
_register('EDIT_OTHER_ENTRIES',
          lazy_gettext(u'can edit another person\'s entries'),
          ENTER_ADMIN_PANEL)
_register('CREATE_PAGES', lazy_gettext(u'can create new pages'),
          ENTER_ADMIN_PANEL)
_register('EDIT_OWN_PAGES', lazy_gettext(u'can edit their own pages'),
          (ENTER_ADMIN_PANEL | CREATE_PAGES))
_register('EDIT_OTHER_PAGES',
          lazy_gettext(u'can edit another person\'s pages'), ENTER_ADMIN_PANEL)
_register('VIEW_DRAFTS', lazy_gettext(u'can view drafts'))
示例#16
0
        if priv is None:
            priv = _Privilege(privilege.name)
        return priv
    return db.association_proxy(lowlevel_attribute, 'privilege',
                                creator=creator_func)


def _register(name, description, privilege_dependencies=None):
    """Register a new builtin privilege."""
    priv = Privilege(name, description, privilege_dependencies)
    DEFAULT_PRIVILEGES[name] = priv
    globals()[name] = priv
    __all__.append(name)


_register('ENTER_ADMIN_PANEL', lazy_gettext(u'can enter admin panel'))
_register('BLOG_ADMIN', lazy_gettext(u'can administer the blog'))
_register('CREATE_ENTRIES', lazy_gettext(u'can create new entries'),
          ENTER_ADMIN_PANEL)
_register('EDIT_OWN_ENTRIES', lazy_gettext(u'can edit their own entries'),
          (ENTER_ADMIN_PANEL | CREATE_ENTRIES))
_register('EDIT_OTHER_ENTRIES', lazy_gettext(u'can edit another person\'s entries'),
          ENTER_ADMIN_PANEL)
_register('CREATE_PAGES', lazy_gettext(u'can create new pages'),
          ENTER_ADMIN_PANEL)
_register('EDIT_OWN_PAGES', lazy_gettext(u'can edit their own pages'),
          (ENTER_ADMIN_PANEL | CREATE_PAGES))
_register('EDIT_OTHER_PAGES', lazy_gettext(u'can edit another person\'s pages'),
          ENTER_ADMIN_PANEL)
_register('VIEW_DRAFTS', lazy_gettext(u'can view drafts'))
_register('MANAGE_CATEGORIES', lazy_gettext(u'can manage categories'),