Esempio n. 1
0
    def index_object(self,idxs=[],log=1):
        """Index this page in the wiki's catalog, if any, and log problems.

        Updates only certain indexes, if specified. 
        """
        if self.hasCatalog() and self.isCatalogable():
            if log:
                BLATHER('indexing',self.url())
            try:
                self.catalog().catalog_object(self,self.url(),idxs)
            except:
                BLATHER('failed to index',self.id(),'\n',formattedTraceback())
Esempio n. 2
0
def initialize(context):
    """Initialize the ZWiki product.
    """
    try:
        # register the wiki page class
        context.registerClass(
            ZWikiPage.ZWikiPage,
            #I want to change the zmi add menu.. but not the meta_type
            #meta_type=Defaults.PAGE_ADD_MENU_NAME,
            permission=Permissions.Add,
            icon='skins/zwiki/wikipage_icon.gif',
            constructors=(
                ZWikiPage.manage_addZWikiPageForm,
                ZWikiPage.manage_addZWikiPage,
            ),
        )

        # also the PersistentOutline class, so it's zmi-manageable
        def outlineConstructorStub(self):
            return MessageDialog(
                title=_("No need to add a Zwiki Outline Cache"),
                message=_("""Zwiki Outline Cache appears in the ZMI Add menu
                for implementation reasons, but should not be added directly.
                Zwiki will create it for you as needed."""))

        context.registerClass(
            OutlineSupport.PersistentOutline,
            permission=Permissions.manage_properties,
            #icon = 'images/ZWikiPage_icon.gif',
            constructors=(outlineConstructorStub, ))
        # set up an "add wiki" menu item
        context.registerClass(
            Folder,
            meta_type=Defaults.WIKI_ADD_MENU_NAME,
            permission=Permissions.AddWiki,
            #icon = 'images/Wiki_icon.gif'
            constructors=(
                manage_addWikiForm,
                manage_addWiki,
                listWikis,
                listZodbWikis,
                listFsWikis,
                addWikiFromFs,
                addWikiFromZodb,
            ))
        initializeForCMF(context)
        initializeForFSS(context)

    # don't let any error prevent initialization
    except:
        INFO('failed to initialise', formattedTraceback())
Esempio n. 3
0
 def index_object(self,idxs=[],log=1):
     """Index this page in the wiki's catalog, if any, and log
     problems.  Updates only certain indexes, if specified.
     """
     if self.hasCatalog() and self.isCatalogable():
         if log: BLATHER('indexing',self.url())
         try:
             # XXX zwiki catalogs prior to 0.60 indexed the text
             # method, it now returns unicode which standard catalogs
             # can't handle, we now index SearchableText instead but
             # the old text index may still be present, we could
             # specify idxs so as to no longer update it
             self.catalog().catalog_object(self,self.url(),idxs)
         except:
             BLATHER('failed to index',self.id(),'\n',formattedTraceback())
Esempio n. 4
0
 def revertEditsEverywhereBy(self, username, REQUEST=None, batch=0):
     """
     Revert all the most recent edits by username throughout the wiki.
     """
     batch = int(batch)
     n = 0
     for p in self.pageObjects():
         if p.last_editor == username:
             n += 1
             try:
                 p.revertEditsBy(username,REQUEST=REQUEST)
             except (IndexError, AttributeError):
                 # IndexError - we don't have a version that old
                 # AttributeError - new object, no history yet,
                 # due to creation of page in unit tests
                 # - doesn't really happen in real use I guess
                 BLATHER('failed to revert edits by %s at %s: %s' \
                         % (username,p.id(),formattedTraceback()))
             if batch and n % batch == 0:
                 BLATHER('committing after %d reverts' % n)
                 get_transaction().commit()
Esempio n. 5
0
    wordboundary = r'\b'
except (TypeError, LookupError):
    # no locale is set, or there was a problem detecting it or a
    # problem decoding its letters.
    # XXX must be a less ugly way to do this:
    # if it's just that there's no locale, don't log a warning
    try:
        lang, encoding = locale.getlocale()
    except locale.Error:
        lang, encoding = -1, -1
    if (lang, encoding) == (None, None): pass
    else:
        BLATHER(
            'the system locale gave a problem in Regexps.py, so WikiNames will not be locale-aware'
        )
        DEBUG(formattedTraceback())
    # define a useful default set of non-ascii letters, mainly european letters
    # from http://zwiki.org/InternationalCharacterExamples
    # XXX more have been added to that page (latvian, polish).. how far
    # should we go with this ?  Could we make it always recognise all
    # letters and forget locale awareness ?  Are regexps getting slow ?
    # XXX needs more work, see failing links at
    # http://zwiki.org/InternationalCharactersInPageNames
    uppercase = string.uppercase + '\xc3\x80\xc3\x81\xc3\x82\xc3\x83\xc3\x84\xc3\x85\xc3\x86\xc3\x88\xc3\x89\xc3\x8a\xc3\x8b\xc3\x8c\xc3\x8d\xc3\x8e\xc3\x8f\xc3\x92\xc3\x93\xc3\x94\xc3\x95\xc3\x96\xc3\x98\xc3\x99\xc3\x9a\xc3\x9b\xc3\x9c\xc3\x9d\xc3\x87\xc3\x90\xc3\x91\xc3\x9e'
    lowercase = string.lowercase + '\xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4\xc3\xa5\xc3\xa6\xc3\xa8\xc3\xa9\xc3\xaa\xc3\xab\xc3\xac\xc3\xad\xc3\xae\xc3\xaf\xc3\xb2\xc3\xb3\xc3\xb4\xc3\xb5\xc3\xb6\xc3\xb8\xc3\xb9\xc3\xba\xc3\xbb\xc3\xbc\xc3\xbd\xc3\xbf\xc2\xb5\xc3\x9f\xc3\xa7\xc3\xb0\xc3\xb1\xc3\xbe'
    U = '|'.join([c.encode('utf8') for c in unicode(uppercase, 'utf-8')])
    L = '|'.join([c.encode('utf8') for c in unicode(lowercase, 'utf-8')])
    Ubr = '[%s]' % ''.join(
        [c.encode('utf8') for c in unicode(uppercase, 'utf-8')])
    Lbr = '[%s]' % ''.join(
        [c.encode('utf8') for c in unicode(lowercase, 'utf-8')])
Esempio n. 6
0
 def sendMailTo(
     self,
     recipients,
     text,
     REQUEST,
     subjectSuffix='',
     subject='',
     message_id=None,
     in_reply_to=None,
     to=None,
     exclude_address=None,
 ):  # -> none; depends on self, wiki, mailhost, time; other effects: sends encoded msg
     """Send a mail-out containing text to a list of email addresses.
     If mail-out is not configured in this wiki or there are no valid
     recipients, do nothing. Log any errors but don't stop.
     text can be body text or rfc-822 message text.
     """
     if not self.isMailoutEnabled(): return
     if exclude_address in recipients:
         recipients.remove(exclude_address)  # help mailin.py avoid loops
     if not recipients: return
     try:
         msgid = message_id or self.messageIdFromTime(self.ZopeTime())
         # encode subject with RFC 2047
         subj = str(
             Header(self.subjectHeader(subject, subjectSuffix),
                    self.encoding()))
         fields = {
             'body':
             '%s\n\n%s' %
             (self.toencoded(text), self.toencoded(self.signature(msgid))),
             'From':
             self.toencoded(self.fromHeader(REQUEST)),
             'Reply-To':
             self.toencoded(self.replyToHeader()),
             'To':
             self.toencoded(to or self.toHeader()),
             'Bcc':
             self.toencoded(self.bccHeader(recipients)),
             'Subject':
             subj,
             'Message-ID':
             self.toencoded(msgid),
             'In-Reply-To':
             self.toencoded(
                 (in_reply_to
                  and '\nIn-reply-to: %s' % in_reply_to.splitlines()[0])
                 or ''),
             'Content-Type':
             'text/plain; charset="%s"' % self.encoding(),
             'charset':
             self.encoding(),
             'X-Zwiki-Version':
             self.zwiki_version(),
             'X-BeenThere':
             self.toencoded(self.xBeenThereHeader()),
             'List-Id':
             self.toencoded(self.listIdHeader()),
             'List-Post':
             self.toencoded(self.listPostHeader()),
             'List-Subscribe':
             '<' + self.pageUrl() + '/subscribeform>',
             'List-Unsubscribe':
             '<' + self.pageUrl() + '/subscribeform>',
             'List-Archive':
             '<' + self.pageUrl() + '>',
             'List-Help':
             '<' + self.wikiUrl() + '>',
         }
         GenericMailHost(self.mailhost()).send(fields)
         BLATHER('sent mail to subscribers:\nTo: %s\nBcc: %s' %
                 (fields['To'], fields['Bcc']))
     except:
         BLATHER('**** failed to send mail to %s: %s' %
                 (recipients, formattedTraceback()))
Esempio n. 7
0
    def upgradeAll(self, render=1, batch=0, REQUEST=None):  # -> none
        # depends on: wiki
        # modifies: wiki (folder, pages, dtml methods, catalog, outline, revisions..)
        """
        Update, upgrade, pre-render and re-index all pages and data structures.

        Normally individual pages are upgraded and pre-rendered on
        demand, when viewed. An administrator may want to do this for
        all pages ahead of time, particularly after a zwiki upgrade,
        to ensure all pages have the latest properties and have been
        rendered by the latest code, minimizing delay and possible
        problems later on.

        Also installs a wiki catalog if not present, re-indexes each
        page, validates page parents, and rebuilds the wiki outline
        cache. Also installs the index_html and standard_error_message
        dtml methods. XXX split ? 

        You can set render=0 to skip the page pre-rendering part,
        completing much faster on large wikis.

        The optional batch argument forces a commit every N pages.
        This may be useful to get a complete run in large/busy wikis,
        which can be difficult due to conflict errors or memory usage.

        Requires 'Manage properties' permission on the folder.
        """
        if not self.checkPermission(Permissions.manage_properties,
                                    self.folder()):
            raise Unauthorized, (
             _('You are not authorized to upgrade all pages.') + \
             _('(folder -> Manage properties)'))

        batch = int(batch)
        if render: BLATHER('upgrading/reindexing/pre-rendering all pages:')
        else: BLATHER('upgrading/reindexing all pages:')
        starttime = clock()
        n, total = 0, self.pageCount()
        self.setupCatalog(reindex=0)
        self.rebuildWikiOutline()
        for p in self.pageObjects():  # poor caching (not a problem here)
            n += 1
            try:
                p.upgrade(REQUEST)
                p.upgradeId(REQUEST)
                p.fixEncoding()
                if render:
                    p.preRender(clear_cache=1)
                    msg = 'upgraded and pre-rendered page'
                else:
                    msg = 'upgraded page'
                # make sure every page is cataloged - slow but thorough
                p.index_object(log=0)
                BLATHER('%s %d/%d %s' % (msg, n, total, p.id()))
            except:
                BLATHER('failed to upgrade page %d/%d %s: %s' \
                     % (n,total,p.id(),formattedTraceback()))
            if batch and n % batch == 0:
                BLATHER('committing')
                get_transaction().commit()
        self.setupDtmlMethods()
        endtime = clock()
        BLATHER('upgrade complete, %d pages processed in %fs, %.1f pages/s' \
                %(n, endtime-starttime, n/(endtime-starttime)))
Esempio n. 8
0
    def upgradeAll(self,render=1,batch=0,REQUEST=None):
                   
        """
        Update, upgrade, pre-render and re-index all pages and data structures.

        Normally individual pages are upgraded and pre-rendered on
        demand, when viewed. An administrator may want to do this for
        all pages ahead of time, particularly after a zwiki upgrade,
        to ensure all pages have the latest properties and have been
        rendered by the latest code, minimizing delay and possible
        problems later on.

        Also installs a wiki catalog if not present, re-indexes each
        page, validates page parents, and rebuilds the wiki outline
        cache. Also installs the index_html and standard_error_message
        dtml methods. XXX split ? 

        You can set render=0 to skip the page pre-rendering part,
        completing much faster on large wikis.

        The optional batch argument forces a commit every N pages.
        This may be useful to get a complete run in large/busy wikis,
        which can be difficult due to conflict errors or memory usage.

        Requires 'Manage properties' permission on the folder.
        """
        if not self.checkPermission(Permissions.manage_properties,
                                     self.folder()):
            raise 'Unauthorized', (
             _('You are not authorized to upgrade all pages.') + \
             _('(folder -> Manage properties)'))
        
        batch = int(batch)
        if render: BLATHER('upgrading/reindexing/pre-rendering all pages:')
        else: BLATHER('upgrading/reindexing all pages:')
        starttime = clock()
        n, total = 0, self.pageCount()
        self.setupCatalog(reindex=0)
        for p in self.pageObjects(): # poor caching (not a problem here)
            n += 1
            try:
                p.upgrade(REQUEST)
                p.upgradeId(REQUEST)
                p.fixPageEncoding()
                if render:
                    p.preRender(clear_cache=1)
                    msg = 'upgraded and pre-rendered page'
                else:
                    msg = 'upgraded page'
                # make sure every page is cataloged - slow but thorough
                p.index_object(log=0)
                BLATHER('%s %d/%d %s'%(msg,n,total,p.id()))
            except:
                BLATHER('failed to upgrade page %d/%d %s: %s' \
                     % (n,total,p.id(),formattedTraceback()))
            if batch and n % batch == 0:
                BLATHER('committing')
                get_transaction().commit()

        self.updateWikiOutline()
        self.setupDtmlMethods()
        endtime = clock()
        BLATHER('upgrade complete, %d pages processed in %fs, %f pages/s' \
                %(n, endtime-starttime, n/(endtime-starttime)))
Esempio n. 9
0
    def sendMailTo(self, recipients, text, REQUEST,
                   subjectSuffix='',
                   subject='',
                   message_id=None,
                   in_reply_to=None,
                   to=None,
                   exclude_address=None,
                   ):
        """
        Send a mail-out containing text to a list of email addresses.

        If mail-out is not configured in this wiki or there are no valid
        recipients, do nothing.  Catch and log any errors when sending
        mail.
        
        XXX templatize ?
        XXX ezmlm won't deliver with precedence: bulk, which these are, what to do
        """
        if not self.isMailoutEnabled(): return

        # gather bits and pieces
        msgid = message_id or self.messageIdFromTime(self.ZopeTime())
        tohdr = to or self.toHeader()

        # do some last-minute winnowing-out of recipients we don't want to
        # send to (and mail we don't want to send)

	# help mailin.py to exclude a list address to avoid a loop
        try: recipients.remove(exclude_address)
        except ValueError: pass

        if not recipients: return
        
	# some lists may deliver duplicated addresses twice; try to avoid
        # unnecessary
        #unique = []
        #for r in recipients:
        #    if not r in unique:
        #        unique.append(r)
        #if self.toProperty() in unique: unique.remove(self.toProperty())

        mailhost = self.mailhost()
        if mailhost.meta_type == 'Secure Mail Host':
            msg = text + "\n\n" +  self.signature(msgid)
            additional_headers = {
                                'Reply-To':self.replyToHeader(), \
                                'X-Zwiki-Version':self.zwiki_version(), \
                                'X-BeenThere':self.xBeenThereHeader(), \
                                'List-Id':self.listIdHeader(), \
                                'List-Post':self.listPostHeader(), \
                                'List-Subscribe':'<'+self.pageUrl()+'/subscribeform>', \
                                'List-Unsubscribe': '<'+self.pageUrl()+'/subscribeform>', \
                                'List-Archive':'<'+self.pageUrl()+'>', \
                                'List-Help':'<'+self.wikiUrl()+'>' }
            if not in_reply_to:
                additional_headers['Message-ID']=msgid
            else:
                additional_headers['Message-ID']=msgid + \
                    '\nIn-reply-to: %s' % in_reply_to.splitlines()[0]
            # XXX should we do error checking and reporting here, similar to below
            # where we do it for normal mail hosts?
            mailhost.secureSend(msg,
                                mto=tohdr,
                                mfrom=self.fromHeader(REQUEST), \
                                subject=self.subjectHeader(subject,subjectSuffix), \
                                mbcc=self.bccHeader(recipients), \
                                charset='utf-8', \
                                **additional_headers )

        else: # normal "Mail Host" or "Maildrop Host"

            msg = """\
From: %s
Reply-To: %s
To: %s
Bcc: %s
Subject: %s
Message-ID: %s%s
X-Zwiki-Version: %s
X-BeenThere: %s
List-Id: %s
List-Post: %s
List-Subscribe: <%s/subscribeform>
List-Unsubscribe: <%s/subscribeform>
List-Archive: <%s>
List-Help: <%s>
Content-Type: text/plain; charset="utf-8"

%s
%s
""" \
            % (self.fromHeader(REQUEST),
               self.replyToHeader(),
               tohdr,
               self.bccHeader(recipients),
               self.subjectHeader(subject,subjectSuffix),
               msgid,
               (in_reply_to and '\nIn-reply-to: %s' % in_reply_to.splitlines()[0]) or '',
               # splitlines to fend off header injection attacks from spammers
               self.zwiki_version(),
               self.xBeenThereHeader(),
               self.listIdHeader(),
               self.listPostHeader(),
               self.pageUrl(),
               self.pageUrl(),
               self.pageUrl(),
               self.wikiUrl(),
               text,
               self.signature(msgid),
               )

            # send
            try:
                mailhost.send(msg)
                #BLATHER('sent mail:\n%s' % msg)
                BLATHER('sent mail to subscribers:\nTo: %s\nBcc: %s' % (
                    tohdr,self.bccHeader(recipients)))

            # if there is any failure, notify admin or log
            except: # XXX this bare except doesn't help for a lot of stuff!
                    # e.g. if the MailHost is configured to an inexisting mail server
                    # only the BLATHER would do anything in that case, 
                    # admin mails fail too of course
                BLATHER('failed to send mail to %s: %s' % (recipients,
                                                           formattedTraceback()))
                admin = getattr(self.folder(),'mail_admin',None)
                if admin:
                    try:
                        self.sendMailTo( #XXX possible infinite recursion ?
                            [],text,REQUEST,
                            subjectSuffix='ERROR, subscriber mailout failed',
                            to=admin)
                    except:
                        BLATHER('failed to send error report to admin: %s' % \
                                formattedTraceback())
Esempio n. 10
0
    L =           '|'.join([c.encode('utf8') for c in unicode(string.lowercase, encoding)])
    Ubr = '[%s]' % ''.join([c.encode('utf8') for c in unicode(string.uppercase, encoding)])
    Lbr = '[%s]' % ''.join([c.encode('utf8') for c in unicode(string.lowercase, encoding)])
    relocaleflag = r'(?L)'
    wordboundary = r'\b'
except:
    # no locale is set, or there was a problem detecting it or a
    # problem decoding its letters.
    # XXX must be a less ugly way to do this:
    # if it's just that there's no locale, don't log a warning
    try: lang, encoding = locale.getlocale()
    except: lang, encoding = -1,-1
    if (lang, encoding) == (None, None): pass
    else:
        BLATHER('the system locale gave a problem in Regexps.py, so WikiNames will not be locale-aware')
        DEBUG(formattedTraceback())
    # define a useful default set of non-ascii letters, mainly european letters
    # from http://zwiki.org/InternationalCharacterExamples
    # XXX more have been added to that page (latvian, polish).. how far
    # should we go with this ?  Could we make it always recognise all
    # letters and forget locale awareness ?  Are regexps getting slow ?
    # XXX needs more work, see failing links at
    # http://zwiki.org/InternationalCharactersInPageNames
    uppercase = string.uppercase + '\xc3\x80\xc3\x81\xc3\x82\xc3\x83\xc3\x84\xc3\x85\xc3\x86\xc3\x88\xc3\x89\xc3\x8a\xc3\x8b\xc3\x8c\xc3\x8d\xc3\x8e\xc3\x8f\xc3\x92\xc3\x93\xc3\x94\xc3\x95\xc3\x96\xc3\x98\xc3\x99\xc3\x9a\xc3\x9b\xc3\x9c\xc3\x9d\xc3\x87\xc3\x90\xc3\x91\xc3\x9e'
    lowercase = string.lowercase + '\xc3\xa0\xc3\xa1\xc3\xa2\xc3\xa3\xc3\xa4\xc3\xa5\xc3\xa6\xc3\xa8\xc3\xa9\xc3\xaa\xc3\xab\xc3\xac\xc3\xad\xc3\xae\xc3\xaf\xc3\xb2\xc3\xb3\xc3\xb4\xc3\xb5\xc3\xb6\xc3\xb8\xc3\xb9\xc3\xba\xc3\xbb\xc3\xbc\xc3\xbd\xc3\xbf\xc2\xb5\xc3\x9f\xc3\xa7\xc3\xb0\xc3\xb1\xc3\xbe'
    U =           '|'.join([c.encode('utf8') for c in unicode(uppercase,'utf-8')])
    L =           '|'.join([c.encode('utf8') for c in unicode(lowercase,'utf-8')])
    Ubr = '[%s]' % ''.join([c.encode('utf8') for c in unicode(uppercase,'utf-8')])
    Lbr = '[%s]' % ''.join([c.encode('utf8') for c in unicode(lowercase,'utf-8')])
    relocaleflag = ''
    wordboundary = '(?<![A-Za-z0-9\x80-\xff])'